Ghostboard pixel

Swift 2.0: API Availability Checking

Swift 2.0: API Availability Checking

Swift is all about safety. With the introduction of the automatic API availability checking in Swift 2.0, there is another great new feature that makes your apps more stable.

Every year Apple releases a new major iOS update, and with each update there are new features and APIs. But since it is not unusual to support at least the previous iOS version, you have to be careful in using these new APIs.

Imagine your deployment target is iOS 8, but you want to support force touch. Before iOS 9, there were some ways of avoiding calling the iOS 9 APIs from iOS 8:

if traitCollection.respondsToSelector(Selector("forceTouchCapability")) {
     if (traitCollection.forceTouchCapability == UIForceTouchCapability.Available) {
          //configure force touch
     }
}
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0)) {
     if (traitCollection.forceTouchCapability == UIForceTouchCapability.Available) {
          //configure force touch
     }
}

The problem with these approaches is, that you have to care of these checks. If you forget a check for new APIs, the app will crash running on an older iOS version.

However, in Xcode 7 and Swift 2.0 the two examples above would not compile! The compiler checks for API availability and you have to use the #available  keyword to get rid of these compiler errors. So in Swift 2.0 your code looks like this:

if #available(iOS 9.0, *) {
     if (traitCollection.forceTouchCapability == UIForceTouchCapability.Available) {
          //configure force touch
     } else {
         // Fallback on earlier versions
}

Guard

Another great idea is to combine the new availability syntax in combination with guard:

func configureForceTouch() {
     guard #available(iOS 9.0, *) else {
          return
     }
        
     if (traitCollection.forceTouchCapability == UIForceTouchCapability.Available) {
         //configure force touch
     }        
}

In this example, the function returns if it runs not on iOS 9 or higher.

Classes and methods

It is also possible to perform the availability check for classes and methods. In this case, you have to use @available instead of #available:

@available(iOS 9.0, *)
     func configureForceTouch() {
          if (traitCollection.forceTouchCapability == UIForceTouchCapability.Available) {
               //configure force touch
           }    
     }
}

Checking other platforms

You can also check for other platforms. For example, we could also check if at least Mac OS X 10.10 is available:

if #available(iOS 9.0, OS X 10.10, *) {
    // runs on iOS 9 and OS X 10.10
}

But what is the star for? It stands for all existing platforms and all potential future platforms. You have to use it, even if you have just an iOS target. You can also specify watchOS and tvOS (since Xcode Beta 7.1):

if #available(OSX 10.0, iOS 9, watchOS 2, tvOS 1, *) {
     // runs on OS X 10.0, iOS 9, watchOS 2 and tvOS 1
}

[thrive_text_block color=”blue” headline=”Conclusion”]The API availability checking feature makes your code safer. However, in order to use the iOS 9 SDK for older projects, you have to do some migration.[/thrive_text_block]

References

Image: @ Gustavo Frazao / shutterstock.com
Swift 2: guard