The @backDeployed attribute in Swift allows you to extend function availability back to older OS versions. It’s beneficial for framework developers to make new declarations available to apps with a lower minimum deployment target compared to the framework.
SE 376 Function Back Deployment introduced the attribute as a proposal, after which it got first implemented by Swift 5.8. Many developers expected this new feature to enable Apple to back-deploy many SwiftUI functions, but it’s not flexible enough. Let’s dive in!
How does the @backDeployed work?
The @backDeployed attribute allows you to back-deploy functions and make them available to apps running on older OS versions.
For example, imagine that we had a new Temperature
type introduced a few years back in iOS 15:
@available(iOS 15, *)
public struct Temperature {
public var degreesCelsius: Double
// ...
}
A few years later, Apple decides to implement an often requested feature in their iOS 17 SDK:
extension Temperature {
@available(iOS 17, *)
public var degreesFahrenheit: Double {
return (degreesCelsius * 9 / 5) + 32
}
}
The availability attribute marks the method as available only for iOS 17 and up. However, the method is self-contained and could run unmodified on older OS versions as we only need the degreesCelsius
input parameter. Therefore, Apple could decide to mark the method as back deployed:
extension Temperature {
@available(iOS 15, *)
@backDeployed(before: iOS 17)
public var degreesFahrenheit: Double {
return (degreesCelsius * 9 / 5) + 32
}
}
We’ve also updated the availability attribute since the method became available as a back-deployed function for older OS versions.
Behavior of back-deployed APIs
To better understand the execution of back-deployed functions, it’s good to look at the final code generated by the compiler:
print(temperature.degreesFahrenheit_bridge)
extension Temperature {
var degreesFahrenheit_bridge: Double {
if #available(iOS 17.0, *) {
/// Call the original parameter since it's available on this OS version.
return degreesFahrenheit
} else {
/// Use the local copy instead.
return degreesFahrenheit_fallback
}
}
}
The compiler creates a bridge between the original property and the back-deployed function. The new bridged property replaces our original reference inside the print statement to ensure older OS versions get supported correctly.
The bridge property checks the API availability and decides to run the original implementation or a copy of the function that gets emitted into the client.
Who should use Function Back Deployment?
Function back deployment is primarily helpful for SDK developers. During normal app development, we bundle our latest library version directly with our app removing the need for @backDeployed attribute usage. In other words, all new code we write will be available immediately and doesn’t require back deployment.
Why can’t Apple back-deploy all new APIs for older OS versions?
Apple will use the @backDeployed attribute whenever possible to make methods available for apps that support older OS versions. You can use GitHub’s search to find examples inside the open-sourced Swift repository:
Back deployment only works with functions, methods, and subscripts. Apple likely does not back-deploy new APIs because of the lack of support to back-deploy new classes and structs to support more extensive API functionalities.
Conclusion
Function back deployment using the @backDeployed attribute is an excellent tool for SDK developers to make their APIs available to clients running older OS versions. While it’s not a solution to back-deploy all new APIs, they already allow you to work with some new self-contained Swift APIs.
If you like to learn more tips on Swift, check out the Swift category page. Feel free to contact me or tweet to me on Twitter if you have any additional tips or feedback.
Thanks!