How to handle API Changes with @available
Table of Contents
In the previous post, How to handle API Changes with #available, we learn a Swift tool to live with changes. But #available
alone can't handle all the cases for API changes. We also need an @available
attribute.
What is an @available attribute
In Swift, there is another tool that helps you cope with API changes, the @available
attribute.
An @available
attribute provides additional information about the declaration. We apply this attribute to limit the usage of a declaration to certain Swift versions or certain platform versions.
Here is an example of marking a function to work only on iOS 15 forward.
@available(iOS 15.0, *)
func addButton() {
var configuration = UIButton.Configuration.filled()
configuration.title = "Click Me"
let button = UIButton(configuration: configuration)
view.addSubview(button)
}
You can easily support sarunw.com by checking out this sponsor.
Translate your app In 1 click: Simplifies app localization and helps you reach more users.
How to use an @available attribute
The available attribute is a declaration attribute, that's means you can apply it to any declaration, e.g., class declaration or method declaration.
The available attributes have the following form:
@available(platform name version number, ..., *)
// class platformSpecificClass {}
// func platformSpeficMethod() {}
We provide a list of comma-separated platforms and versions that you want and end with an asterisk (*
). You can check out all available platforms here.
Why do we need an @available attribute
As you can see, the main function of the available attribute seems to be on the API creator side, where you can limit class or function declaration to a specific platform version.
How can this tool help us to handle changes?
The type of change that we usually need available attribute is a change that introduce a new approach to the system. This kind of change usually causes us to have two sets of implementation, one for the new flow and one for the old approach.
It is easier to understand with an example.
SceneDelegate
When Apple adds support for multiple windows in iOS 13, it dramatically changes its entire app life cycle. We have a new method in UIApplicationDelegate
and a new UISceneDelegate
protocol.
SceneDelegate
can't live in an old iOS version but is required in a new one. Availability condition can't help you on this since statements are not allowed at the top level.
We can't do something like this with #available
.
if #available(iOS 13, *) {
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// ...
}
}
But we can do that with the available attribute.
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// ...
}
An available attribute also helps in a case where a new approach and an old one need to co-exist, like in AppDelegate
where we can scope usage of some delegate method to a specific platform version.
We can do something like this if we want to listen to the UISceneSession
lifecycle.
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: UISceneSession Lifecycle
@available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
@available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {}
}
You can easily support sarunw.com by checking out this sponsor.
Translate your app In 1 click: Simplifies app localization and helps you reach more users.
Conclusion
The available attribute (@available
) has broader functionality than the availability condition (#available
). I sit far more to the side of the API creator, but as you can see, it also benefits on an API consumer side.
In a future post, I will explore the full potential of @available
and how it can benefit API creators.
Read more article about Swift or see all available topic
Enjoy the read?
If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.
Become a patron Buy me a coffee Tweet ShareHow to create observable variables from other observable variables in GetX
Learn how to make derived variables observable in GetX.
How to prepare your iOS project to support modular architecture
At the beginning of a project, there are a lot of changes and uncertainty. You might want to start modularizing your code in the later phase, where the scope is clearer. Let's see how to prepare your single module project to support future modularizing.