Skip to content

API Availability (Swift)

A SwiftUI guide for coding agents. Also covers available check ios version, unavailable attribute, deprecated obsoleted swift, backdeployed attribute, backport view modifier, version gating.

Swift gates new APIs behind availability checks at the call site and availability attributes at the declaration. #available branches at runtime; @available documents the contract to the compiler.

Checking at the Call Site

#available runs the new branch when the platform supports it; #unavailable flips the test.

if #available(iOS 16, *) {
    // Use new APIs
} else {
    // Use old APIs
}

if #unavailable(iOS 16) {
    // Use old APIs
}

Declaring Availability

@available marks the platforms a declaration needs. This is the pattern for backporting: the wrapper is available early and branches to the real API when it exists.

extension View {
    @available(iOS 14, macOS 11, *)
    func backportedTask<Value: Equatable>(
        id: Value,
        task: @Sendable @escaping () async -> Void
    ) -> some View {
        if #available(iOS 15, macOS 12, *) {
            return self.task(id: id, task)
        } else {
            return self.onChange(of: id) { _ in
                Task { await task() }
            }
        }
    }
}

Deprecation Lifecycle

The long form tracks a lifecycle per platform. A deprecated version produces a compiler warning at that target; an obsoleted version produces a compiler error. message adds text to the diagnostic, and renamed gives Xcode a fix-it that rewrites the call site.

@available(iOS, introduced: 14, deprecated: 16, obsoleted: 17, renamed: "task")
@available(macOS, introduced: 11, deprecated: 12, obsoleted: 13)

Back Deployment

@backDeployed, from Swift 5.8, ships a fallback implementation to older OS versions while the new OS uses its own copy. Library authors use it so callers get one API name on every version.

extension View {
    @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
    @backDeployed(before: iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0)
    func task<Value: Equatable>(
        id: Value,
        closure: @Sendable @escaping () async -> Void
    ) -> some View {
        self.onChange(of: id) { _ in
            Task { await closure() }
        }
    }
}

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-api-availability-in-swift" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems