---
id: deprecated-apis
title: Deprecated and outdated SwiftUI APIs
platforms: [iOS, iPadOS, macOS]
generated-from: agent/src/corrections.yaml
reviewed: 2026-10-26
---

# Deprecated and outdated SwiftUI APIs

<!-- Generated by agent/src/make_deprecated_topic.py from corrections.yaml. Edit that file, not this one. -->

Models trained on older code keep writing the left side. Write the right side when your deployment target is at least the version in parentheses; below it, keep the old form or gate the new one with `if #available`. Versions are iOS; the macOS floor matches (iOS 13–18 = macOS 10.15–15, and 26+ is the same number). No version means any OS. `check-swift.sh` flags every row.

## Deprecated, and the compiler warns

Fix these now.

- `NavigationLink(isActive:)` / `(tag:selection:)` → `.navigationDestination(isPresented:)` / `NavigationLink(value:)` (16)
- `.onChange(of:) { new in }` → `{ old, new in }` or `{ }` (17)
- `Text + Text` → `Text("a \(Text(b).bold())")` (14)
- `.animation(_:)` → `.animation(_:value:)` / `withAnimation` (13)
- `UIScreen.main.bounds` → `.containerRelativeFrame` / size classes (17)

## Deprecated or superseded

Many are deprecated only in Apple's docs so far, so nothing warns. Don't write them in new code. `ObservableObject` never warns, but `@Observable` views update only for properties they read; don't mix the two systems in one model.

- `NavigationView` → `NavigationStack` / `NavigationSplitView` (16)
- `.navigationViewStyle(_:)` → delete; pick the container (16)
- `.navigationBarTitle` → `.navigationTitle` + `.navigationBarTitleDisplayMode` (14)
- `.navigationBarItems` → `.toolbar { ToolbarItem }` (14)
- `.navigationBarLeading/Trailing` → `.topBarLeading/Trailing` (14)
- `.navigationBarHidden(true)` → `.toolbarVisibility(.hidden, for: .navigationBar)` (18)
- `.tabItem { }` → `Tab("Title", systemImage:) { }` (18)
- `\.presentationMode` → `\.dismiss` (15)
- `ActionSheet` / `.actionSheet` → `.confirmationDialog` (15)
- `Alert(title:)` → `.alert(_:isPresented:actions:message:)` (15)
- `ObservableObject` → `@Observable` (17)
- `@Published var` → plain `var` in an `@Observable` class (17)
- `@StateObject` → `@State` (17)
- `@ObservedObject` → plain property, or `@Bindable` (17)
- `@EnvironmentObject` → `@Environment(Model.self)` (17)
- `.environmentObject(x)` → `.environment(x)` (17)
- `DispatchQueue.main.async` in views → `.task { }` + async/await
- `DispatchQueue.main.asyncAfter` → `Task.sleep(for:)` in `.task` (16)
- `.onAppear { Task { } }` → `.task { }` (15)
- `.foregroundColor` → `.foregroundStyle` (15)
- `.cornerRadius(r)` → `.clipShape(.rect(cornerRadius: r))`
- `.accentColor(_:)` → `.tint(_:)` (15)
- `.edgesIgnoringSafeArea` → `.ignoresSafeArea` (14)
- `.overlay(v, alignment:)` → `.overlay(alignment:) { v }` (15)
- `Color(UIColor.x)` / `Color(.systemX)` → `Color(uiColor:)` or a SwiftUI style (15)
- `.background(GeometryReader…)` size hack → `.onGeometryChange` (16)
- `MagnificationGesture` / `RotationGesture` → `MagnifyGesture` / `RotateGesture` (17)
- `.autocapitalization` → `.textInputAutocapitalization` (15)
- `.disableAutocorrection` → `.autocorrectionDisabled` (13)
- `TextField(onCommit:)` → `.onSubmit` + `@FocusState` (15)
- `resignFirstResponder` → `@FocusState` (15)
- `.accessibility(label:)` → `.accessibilityLabel` (14)
- `\.sizeCategory` → `\.dynamicTypeSize` (15)
- `Section(header:)` → `Section("Title")` / `Section { } header: { }` (15)
- `PreviewProvider` → `#Preview`

## Judgment calls

Usually wrong in new code, sometimes right. Decide case by case.

- `@State var` → `@State private var`
- `ForEach(items, id: \.self)` → `Identifiable` items
- `ForEach(items.indices)` → `ForEach(items)` / `ForEach($items)`
- `.buttonStyle(PlainButtonStyle())` → `.buttonStyle(.plain)` (15)
- `GeometryReader` + `size.width * k` → `.containerRelativeFrame` (17)
- `AnyView` → `@ViewBuilder` + `some View`
- `UIApplication.shared.open` → `@Environment(\.openURL)` (14)
- `userInterfaceIdiom == .pad` → size classes / `ViewThatFits`
- `.textFieldStyle(.roundedBorder)` → `.bordered` + `.textInputBorderShape` (27)
- `FileDocument` → `Document` (`ReadableDocument` & `WritableDocument`) (27)

## Apple docs

- https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro.md
- https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types.md
- https://developer.apple.com/documentation/updates/swiftui.md
