[aerogear-dev] Swift running on iOS 7 / Observations

Christos Vasilakis cvasilak at gmail.com
Fri Aug 1 06:47:16 EDT 2014


Hi all,

a heads up on my observations during porting our quickstart app [1]  (Swift port) and making it  compatible to also run on iOS 7 too [2]. Indeed, Swift apps can run on iOS 7 due to the swift-runtime embedded in the application (and can be observed on the generated app archive [3] ).

A major obstacle faced is that although you can utilise at runtime a form of dynamic version check (e.g. respondsToSelector[] ) to decide to call either iOS 7 or iOS 8 API, the runtime is strict on class loading and fails even when the code-path that instantiates the class is not executed.

Let me give you a concrete example. Here is snippet of code that uses either the new push registration API available in iOS 8 or fails back to the old one if not:

--
if application.respondsToSelector(Selector("registerUserNotificationSettings:")) {
    let settings = UIUserNotificationSettings(forTypes: .Alert | .Badge | .Sound, categories: nil)
    UIApplication.sharedApplication().registerUserNotificationSettings(settings)
    UIApplication.sharedApplication().registerForRemoteNotifications()
} else {
    UIApplication.sharedApplication().registerForRemoteNotificationTypes( .Badge | .Sound | .Alert)
} 

If your Target build SDK is set to ‘Latest (8.0)’ (to avoid compilation error of missing classes) but your deployment target is set to 7.x (to support older versions) and you have some form of dynamic selection on runtime (e.g .respondsToSelector[] ), this fails when running on iOS 7 with a missing symbol:  (note that the code path that instantiates UIUserNotificationSettings is not reached but yet fails at runtime)

--
dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings
  Referenced from: /var/mobile/Applications/E8C53BD1-285E-4DDD-B71C-C99D61195671/Contacts.app/Contacts
  Expected in: /System/Library/Frameworks/UIKit.framework/UIKit
 in /var/mobile/Applications/E8C53BD1-285E-4DDD-B71C-C99D61195671/Contacts.app/Contacts
--

In contrast, the obj-c  version of the same code runs fine on iOS 7. 

Apparently this has been observed [4] and some workarounds exist (basically use an objective-c bridge to workaround it, but that is just a ‘hack'). This is to the fact that the obj-c compiler does some form of weak-linking the symbols that are only available on later versions than the deployment target.

I imagine having the same form of issues when trying to utilise a any new iOS 8 class that doesn’t exist on iOS 7. For that matter (at least for the current state of the Swift runtime) i am leading towards not using any hacks to workaround issues on Swift running on iOS 7.  I am sure Apple with the current pace of dev will come up with techniques, but let’s not pollute the code for the time being.

Let me know your thoughts.

-
Christos

[1] https://github.com/aerogear/aerogear-push-quickstarts/tree/swift
[2] https://github.com/cvasilak/aerogear-push-quickstarts/tree/swift-ios7
[3] http://tinyurl.com/swift-runtime
[4] http://stackoverflow.com/questions/24256583/swift-write-code-for-ios-7-and-8


More information about the aerogear-dev mailing list