Conditionally import a framework (such as Speech) based on iOS Version in Swift?

Is there any way to conditionally import a framework in Swift based on runtime iOS version?


In particular, I have an app with a deployment target of iOS 8. I would like to use the new Apple Speech framework in the app, if it is available at runtime. I am aware of the #available(iOS 10, *) directive for code sections, and the @available(iOS 10, *) directive which can be used for an entire class. So I can easily avoid executing any code that uses the Speech framework with those. But in the file that contains the class that uses Speech, I need the "import Speech" statement, and neither of those two directives can be used there. I am finding that even if I have the @available(iOS 10, *) directive on my entire class, when I run my app on an iOS 9 device it is killed at launch with "dyld: Library not loaded: /System/Library/Frameworks/Speech.framework/Speech".


Am I missing something, or is it only possible to use the Speech framework in an app that has deployment target of 10?

Answered by Pmatt_PI in 157652022

That does not work in this case, because it is a compile-time directive. And I definitely need to compile in the Speech Framework reference, and current Swift will always be available at build time. It is run time, on an iOS 9 device, that is the issue.


I also posted this on Stackoverflow -- http://stackoverflow.com/questions/38536956/conditionally-import-a-framework-such-as-speech-based-on-ios-version-in-swift/38538861


It turns out that the key is to mark the Speech frame work as Optional during the link phase.


What is interesting is that on iOS 10, you don't have to explicitly add the Speech framework at all for the app to work (and Apple's sample SpeakToMe project does not). But if you do go ahead and add it, then mark as Optional (and use @available and #available to avoid executing it), it does run on iOS 9.

Use the "#if swift(>x.y)" preprocessor directive.

Accepted Answer

That does not work in this case, because it is a compile-time directive. And I definitely need to compile in the Speech Framework reference, and current Swift will always be available at build time. It is run time, on an iOS 9 device, that is the issue.


I also posted this on Stackoverflow -- http://stackoverflow.com/questions/38536956/conditionally-import-a-framework-such-as-speech-based-on-ios-version-in-swift/38538861


It turns out that the key is to mark the Speech frame work as Optional during the link phase.


What is interesting is that on iOS 10, you don't have to explicitly add the Speech framework at all for the app to work (and Apple's sample SpeakToMe project does not). But if you do go ahead and add it, then mark as Optional (and use @available and #available to avoid executing it), it does run on iOS 9.

What is interesting is that on iOS 10, you don't have to explicitly add the Speech framework at all for the app to work (and Apple's sample SpeakToMe project does not).

That’s the Link Frameworks Automatically (

CLANG_MODULES_AUTOLINK
) feature kicking in. It’s weird that this is not automatically marking the Speech framework as optional based on your deployment target. Please file a bug about that, then post your bug number here, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you. My use of the Speech Framework is device focused on the Apple Watch OS 3. Your answer suggests that the rror I get when using the import Speech framework isn't fully set in the beta. Is that correct?

Conditionally import a framework (such as Speech) based on iOS Version in Swift?
 
 
Q