Review the methods of Objective-c
Before looking at Swift, let's briefly review our previous methods of checking the usability of the SDK with Objective-c.
Checking the availability of classes and frameworks
IOS 9 has introduced many new frameworks as an important version. But if you deploy a version lower than iOS 9, you need a weak connection (weak link) for these new frameworks, and then check the availability of their classes at run time. For example: if we want to use the new contact Framework (Contacts framework) in iOS 9 and use the old Address Book Framework (AddressBook Framework) in iOS 8:
123456 |
if ([Cncontactstore class]) {    cncontactstore *store = [ cncontactstore new ];    //... }  else {    // using the old frame } |
Checking the availability of methods
Use Respondstoselector to check if this method is included in the frame. For example: IOS 9 has a new allowsbackgroundlocationupdates attribute in the core location framework:
12345 |
CLLOCATIONMANAGER *MANAGER = [CLLOCATIONMANAGER  new ]; if ([Manager respondstoselector: @selector ( Setallowsbackgroundlocationupdates:)] {    // not available in ios 8    manager.allowsbackgroundlocationupdates = yes; } |
Trap
These methods are difficult to maintain, and they are not as secure as they seem. Perhaps an API is now public, but it may be private in earlier versions. For example: IOS 9 has several new text styles, such as uifonttextstylecallout. If you only want to use this style in iOS 9, you can check that it exists because it should be null in iOS 8:
123 |
if (UIFontTextStyleCallout) { textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCallout]; } |
Unfortunately, the result is not so. It turns out that this flag exists in iOS 8, but it's not declared public. Using a private method or value can have unpredictable results, and this is different from what we think.
Method of Swift 2
The
Swift 2 has built-in usability checks and is checked at compile time. This means that when we use an API that is not available for the current deployment version, Xcode can notify us. For example, if I use Cncontactstore,xcode in a deployment version of iOS 8, the following improvements will be made:
12345 |
if #available(iOS 9.0, *) { let store = CNContactStore() } else { // 旧版本的情况 } |
It can also replace the respondstoselector we used earlier:
1234 |
let manager = CLLocationManager() if #available(iOS 9.0, *) { manager.allowsBackgroundLocationUpdates = true } |
Usage Scenarios for usability checks
#available条件适用于一系列平台 (IOS, OSX, WatchOS) and version numbers. For example, for code that runs only on iOS 9 or OS X 10.10:
123 |
if #available(iOS 9, OSX 10.10, *) { // 将在iOS 9或OS X 10.10上执行的代码 } |
Even if your app is not deployed on other platforms, you will need to include them with the * wildcard characters at the end.
If a block of code is executed only on a specific platform version, you can return it in advance with the guard declaration with #available, which will enhance readability:
12345678 |
private func somethingNew() {
guard #available(iOS 9, *) else { return } // 在iOS 9中执行的代码 let store = CNContactStore() let predicate = CNContact.predicateForContactsMatchingName( "Zakroff" ) let keys = [CNContactGivenNameKey, CNContactFamilyNameKey] ... }
|
If the entire method or class exists only under a specific platform version, use @available:
12345 |
@available(iOS 9.0, *) private func checkContact() { let store = CNContactStore() // ... } |
Compile-time Security checks
Before we finish, let's look at the constant in iOS 9 that is public but private in iOS 8. If the deployment version is iOS 8, we set the font to a style that only iOS 9 can use, which results in a compilation error:
12 |
label.font = UIFont.preferredFontForTextStyle(UIFontTextStyleCallout) > ‘UIFontTextStyleCallout‘ is only available on iOS 9.0 or newer |
Swift makes it easy to debug and can assign a reasonable value to the platform version:
12345 |
if #available (ios 9.0, *) {    label.font = uifont.preferredfontfortextstyle (uifonttextstylecallout) }  else {    label.font = uifont.preferredfontfortextstyle (uifonttextstylebody) |
Learn more about learning about iOS at the Ding Xue School
Check the availability of PAI in Swift