I have an open source Swift framework (https://flint.tools) that I want to use to wrap new Siri Shortcuts APIs. However I don't want to force all the users of my framework to build with Xcode 10 (now or in future).
I don't believe I can achieve this with the current compile and runtime availability checks in Swift.
Here's an example:
#if os(iOS) || os(watchOS)
if #available(iOS 12, watchOS 5, *) {
// Here's the new API
myActivity.isEligibleForPrediction = true
}
#endif
I can build this in Xcode 10, it works as expected at runtime. However I can't compile on Xcode 9.x because isEligibleForPrediction is not a valid symbol on Xcode 9.x contemporary SDKs.
Because this is a compile time constraint, it doesn't seem possible to tell Swift "Only compile this code if the target SDK is iOS >= 12 or watchOS >= 5" so that users of my framework who are not able to build on the latest and greatest can still use it.
Maintaining multiple branches over time is very painful.
I believe this can currently be accomplished by a workaround with a Swift version check:
#if swift(>=4.2) && (os(iOS) || os(watchOS))
if #available(iOS 12, watchOS 5, *) {
// Here's the new API
myActivity.isEligibleForPrediction = true
}
#endif
This would ensure that the availability check is only visible to the compiler when in Swift 4.2 and later, which is included in Xcode 10, where the symbol is first available.
That said, this is a workaround to your issue rather than a feature to handle these cases for Target SDK and I think it’s something that definitely needs addressing.
Also please note that this workaround doesn’t work if it is in Swift 3 compatibility mode. You can construct a more convoluted check around this, but a proposal documenting it and a more improved version was recently approved and should end up in the final Swift 4.2 I believe.
Personally I’d be in favour of this, yes. I think it’s clean at first glance. Would love to hear what others think of this...
Or maybe could use the os directives for consistency... though this could get confusing for whether you are compiling for that SDK or just running on a device running that version of the os...:
Hmm @Rod_Brown sadly the swift 4.2 option isn't really viable. There seems to be no way to make projects use the latest available Swift version, and conversion to Swift 4.2 involves other changes.
I think #if canImport(Network) is the only "safe" way and it is very ugly.
Makes sense. I think the fact we have to check for the import ability of an irrelevant framework reveals this is an area that needs work. Hopefully the pitch @felix91gr mentioned can address this issue...