[swift-users] Check deployment target at runtime or compile time
Ole Begemann
ole at oleb.net
Wed Feb 15 13:11:24 CST 2017
In macOS 10.12 and iOS 10.0, class properties were introduced to
Objective-C [1]. I noticed that the Objective-C runtime treats class
properties differently based on the deployment target. Example:
// MyClass is an Objective-C class that has a class property
let metaclass = object_getClass(MyClass.self)
var count: UInt32 = 0
let properties = class_copyPropertyList(metaclass, &count)
// Work with properties
// Deallocate properties
When the deployment target is macOS 10.12, passing a metaclass to
copyPropertyList() returns the class properties, but it returns an empty
list on a lower deployment target.
I'd like to perform a check (either at runtime or compile time) which of
these behaviors I'll get.
I didn't find a way to perform a compile-time check in Swift against the
deployment target; if #available() checks against the SDK the code is
linked against. Likewise, the usual runtime check using
ProcessInfo().isOperatingSystemAtLeast() doesn't check against the
deployment target.
The best I came up with is this:
/**
Returns `true` if the current deployment target is at least the
specified version that corresponds to the current platform.
The arguments must be passed in the form of the `__MAC_XX_X`,
`__IPHONE_XX_X`, etc. constants defined in Availability.h.
*/
public func isDeploymentTargetAtLeast(
macOS macOSVersion: Int32, iOS iOSVersion: Int32,
tvOS tvOSVersion: Int32, watchOS watchOSVersion: Int32) -> Bool {
#if os(macOS)
return __MAC_OS_X_VERSION_MIN_REQUIRED >= macOSVersion
#elseif os(iOS)
return __IPHONE_OS_VERSION_MIN_REQUIRED >= iOSVersion
#elseif os(tvOS)
return __TV_OS_VERSION_MIN_REQUIRED >= tvOSVersion
#elseif os(watchOS)
return __WATCH_OS_VERSION_MIN_REQUIRED >= watchOSVersion
#else
return false
#endif
}
For example, to test if the current deployment target is at least macOS
10.12, iOS 10.0, tvOS 10.0, or watchOS 3.0:
guard isDeploymentTargetAtLeast(
macOS: __MAC_10_12, iOS: __IPHONE_10_0,
tvOS: __TVOS_10_0, watchOS: __WATCHOS_3_0) else {
// Deployment target is lower
...
}
Is this correct? Is there a better way to do this?
[1]: http://useyourloaf.com/blog/objective-c-class-properties/
More information about the swift-users
mailing list