Swift provides first-class constructs for dealing with API changes, deprecate some old APIs to make room for the new ones. Designed directly into the language, they work with the compiler and with you to streamline the process of adding cross-platform and version compatibility to your project.
Apply this attribute to indicate a declaration’s life cycle relative to certain platform version or Swift language version. You will get a compile error when trying to use a new API on an older version.
// (1) Platform availability
@available(iOS 16, *)
@available(iOS 16, macOS 13, *)
// (2) With introduced, deprecated, and/or obsoleted
@available(iOS, introduced: 16)
@available(macOS, introduced: 13)
@available(iOS, deprecated: 13, renamed: "foo")
@available(iOS, introduced: 10, deprecated: 13, message: "foo")
// (3) With unavailable
@available(iOS, unavailable, renamed: "foo")
@available(*, unavailable, renamed: "foo")
// (4) Swift version availability
@available(swift 5.7)
@available(swift, deprecated: 5.6, message: "Deprecated in 5.6")
You use this attribute with following platform/language name:
- swift
- iOS, macOS, macCatalyst, watchOS, tvOS
- iOSApplicationExtension
- macOSApplicationExtension
- macCatalystApplicationExtension
- watchOSApplicationExtension
- tvOSApplicationExtension
(1) -> You provide a list of comma-separated platforms that you want and end with an asterisk (*) which is required to handle potential future platforms. When an API is marked as available in iOS, it’s implicitly marked available on tvOS and Mac Catalyst, because both of those platforms are derivatives of iOS.
(4) -> If you want to support development of your app with previous versions of Xcode or for your Swift package to work for multiple Swift compiler toolchains, you can use the @available attribute to annotate declarations containing new language features.
(3) -> If necessary, you can explicitly mark these derived platforms as being unavailable
with additional @available attributes. The unavailable
availability overrides all other availability information.
@available(iOS 16, *)
@available(tvOS, unavailable)
@available(macCatalyst, unavailable)
class Foo {
//...
}
(1)/(2) + (4) -> You can apply multiple available attributes on a single declaration to specify the declaration’s availability on different platforms and different versions of Swift.
@available(swift 5.7)
@available(iOS 16, macOS 13, *)
class Foo {
//...
}
(4) -> Only unavailable
and deprecated
are supported for Swift availability.
Swift historically supported the #available
condition to check if a specific symbol is available for usage.
if #available(iOS 16, *) {
// Do something with iOS 16 onwards
} else {
// Fallback on earlier versions
}
Because the availability condition is not parsed as an expression, it cannot be negated with regular boolean operations (!
/== false
). The way instead is to make use of the else
clause, but as unavailability checks are not interested at all in the positive portion of the check, doing so will leave behind an empty if branch.
if #available(iOS 16, *) {
// no-op
} else {
// if NOT in iOS 16, doSomething.
doSomething()
}
Swift 5.6 introduced #unavailable
condition to improve the readability of the unavailability check. A negative availability condition might also be necessary in cases where an API is marked as deprecated (and documented as non-functional) in newer OS versions.
if #unavailable(iOS 16, *) {
doSomething()
}