Skip to content

Deprecating Your Own Convenience API (SwiftUI)

A SwiftUI guide for coding agents. Also covers available deprecated obsoleted, version bridge dead code, compatibility shim cleanup, availability annotation own code, compiler reminder remove wrapper, ios version bridging labelstyle.

Every OS-bridging wrapper you write, code that picks a new API on the new OS and a fallback on the old one, becomes dead code the day you raise the deployment target. Annotate it with @available(deprecated:obsoleted:) at creation time, and the compiler finds it for you later.

The wrapper that will die

A typical bridge: iOS 26 toolbars show symbols, iOS 18 toolbars show text. A LabelStyle switches on availability.

struct ToolbarLabelStyle: LabelStyle {
  func makeBody(configuration: Configuration) -> some View {
    if #available(iOS 26, *) {
      Label(configuration).labelStyle(.iconOnly)
    } else {
      Label(configuration).labelStyle(.titleOnly)
    }
  }
}

extension LabelStyle where Self == ToolbarLabelStyle {
  static var toolbar: Self { .init() }
}

Once the app targets iOS 26 the whole type is pointless, and there may be dozens of such helpers scattered around.

Annotate the expiry when you write it

Add the availability annotation to the convenience entry point. When the deployment target reaches the deprecated version, every use site becomes a warning with your message; at the obsoleted version it becomes a compile error.

extension LabelStyle where Self == ToolbarLabelStyle {
  @available(iOS, deprecated: 26, obsoleted: 27, message: "You don't need .toolbar anymore")
  static var toolbar: Self { .init() }
}

Deprecate first, then obsolete

Setting obsoleted: 26 directly produces errors on the target bump, which can block unrelated work. Prefer the two-step ramp: deprecate at the version that makes the wrapper redundant, and obsolete one version later. Then treat the warnings as the cleanup queue rather than letting them accumulate.

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-deprecating-your-own-convenience-api" })
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