Swift behaves differently on debug and release mode
Asked Answered
H

4

11

Not sure if that's an issue with Swift, XCode or Alamofire but I recognized strange behavior on different places within my mixed Swift/Objc app. It only happens in parts which are written in Swift and use closures/networking. Here's an example code where it happens:

Alamofire.request(.DELETE, "http://someUrl.com/user", parameters: nil)
     .response { (request, response, data, error) in
                 // some cleanup code and an alert
               }

When I run my app in Debug mode on my iPhone then it all just works, the cleanup code and the alert get presented like they should when I do the "delete account" action which runs the code above.

But when I send my app to users via Testflight or run my app on the same iPhone directly but using the Release build configuration then the cleanup code doesn't run and the alert doesn't show up. It looks like the whole closure doesn't get called.

Does anyone have experiences with such strange behaviors and knows how to prevent them? I'm not sure what's the issue here, therefore it is hard for me to figure out a solution that works on both Debug and Release modes.

Thank you for any help!

The environment: I'm using Alamofire 1.1.3 as an embedded framework integrated to my project as a git submodule. The app runs on iOS 8+ only, I have iOS 8.1.2 installed on my iPhone 6.

Hindoo answered 26/1, 2015 at 15:23 Comment(2)
YES, I am having the same problem. My closures are actually executing the wrong closures and some of my closures are not executing at all!Ballocks
Upgrading to Xcode 6.3 fixed this.Ballocks
J
4

I've had some similar issues when building for release in a project similar to yours(Swift + Objective-C), in my case it was skipping a piece of code within a loop, but it was not skipping the loop itself. In order to solve this we changed at the Build Settings -> Apple LLVM 6.0 Code Generation -> Optimization Level the value of Debug to Fastest, Smallest [-Os], which was the same of Release and then we got the same bug on Debug. Then we tried to changing both to None [-O0] (Which is Debug default value) but it only made the bug disappear on Debug mode not in Release, so we had to workaround that code and change a little bit of the UI.

I would like to believe that it's something the compiler does in Release that can't be changed by us, so maybe it's an Xcode Bug.

Jungle answered 26/1, 2015 at 15:59 Comment(6)
Thank you, that will at least help me debug the issue to find a workaround. I'll post a bug report to Apple and will keep you updated.Hindoo
Okay, I set both the Apple LLVM 6.0 - Code Generation and the Swift Compiler - Code Generation to the same in Debug mode as in Release mode and indeed: The bug now also appears when running in Debug mode. But when I set a breakpoint to the code that doesn't run successfully then XCode crashes. I could reproduce that behavior three times in row. Bad news ... :(Hindoo
We never thought of setting a breakpoint, but I guess we would have had the same result. Thanks for reporting it to Apple, hopefully they will fix it soon, until then we have to keep the ugly workaround as well. If I find anything that could help us I will post it here. Thanks :)Jungle
Please note that setting breakpoints in the source code and then running optimised code is not really a 1:1 relationship. This is one of the reasons why debug builds shan't optimise.Bigeye
So this is happening to me on a dependency which I can't control and go around that code. I guess I'm better off changing that dependency... :/ Is turning of Optimization level a viable solution (it works but..) ? This is really inconvenient...Vireo
@NunoGonçalves You can change the Optimization Level depending on your needs, this answer can help you decide what would be the best option for you. You could also tell us what does that dependency do, so we can suggest you an alternative in case you want to keep the Optimization Level as it is right now.Jungle
H
2

It's not a real solution, but as a workaround it worked to just not put the code inside a completion handler. Instead it is now part of a method (all context variables need to be accessible within that method of course) and I save the type of request I make.

When the request method from my above example runs and checks if it has a completion closure code to run I additionally added a check for the type and if it's the type where the bug happened then it simply calls that method where the completion code now is in.

This of course is very ugly but until Apple fixes this bug (I sent them a bug report with example code) I can't figure out any other solution. Maybe this workaround helps someone else as well. If my description is confusing just tell me and I will try to be clearer with some example code.

Hindoo answered 27/1, 2015 at 23:16 Comment(0)
M
2

The answer could be the previous one I gave to the question App crashes in Release build but not in debug.


Apple also describes a known issue. I describe it briefly in case someone is look for answer and the previous solution doesn't work.

Check your crashlog for errors like

Dyld Error Message:
  Library not loaded: @rpath/libswiftCore.dylib

or

[....] [deny-mmap] mapped file has no team identifier and is not a platform binary:
/private/var/mobile/Containers/Bundle/Application/5D8FB2F7-1083-4564-94B2-0CB7DC75C9D1/YourAppNameHere.app/Frameworks/libswiftCore.dylib

and follow apple guidance if you have similar crash output like the one above.

PS: You could check the log easily even under Window ->Device in XCode. click to the device and click view device logs.

Morette answered 28/7, 2015 at 10:13 Comment(0)
I
0

1 - go to project setting

2 - select TARGETS

3 - select build settings

4 - search on 'Optimization Level'

5 - set No Optimization in Debug and Release

6 - Run your app

for more info read a Optimizing Your iOS App Build: Speed vs Size

Izaguirre answered 15/7, 2024 at 8:10 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.