【SwiftUI】 Xcode 27 でアラートが Bool なしで出せるようになった

【SwiftUI】 Xcode 27 でアラートが Bool なしで出せるようになった

Xcode 27で追加されたSwiftUIの新しい`alert`APIを試してみました。Optional の Binding を渡すだけで表示でき、表示フラグの`Bool`が不要になる便利な機能です。従来の書き方との違いと実装のポイントをまとめます。
2026.10.11

はじめに

Xcode 27(iOS 27.0 SDK)で、SwiftUI の alert に Optional の Binding を渡すだけで表示できるAPIが追加されたので、実際に使ってみました。エラー用の alert(error:) と、任意の値を渡せる alert(_:item:) です。

これまでは表示フラグの Bool を別に持つ必要があったので、それがどう変わるのかを従来の書き方と比べてみます。

検証環境

  • Xcode 27
  • iOS 27.0 Simulator

エラーを表示する

従来の書き方

LocalizedError を渡してアラートを出す alert(isPresented:error:) は、表示フラグの Binding<Bool> が必須でした。

struct ContentView: View {
    @State private var isPresented = false
    @State private var error: SampleLocalizedError?

    var body: some View {
        Button("読み込む") {
            Task {
                do {
                    try await load()
                } catch let error as SampleLocalizedError {
                    self.error = error
                    isPresented = true
                } catch {}
            }
        }
        .alert(isPresented: $isPresented, error: error) { _ in
            Button("OK") {}
        } message: { error in
            Text(error.recoverySuggestion ?? "")
        }
    }
}

エラーの値と Bool の2つの State を持って、両方を更新する必要があります。閉じると Bool は false に戻りますが、エラーの値は残ったままでした。

Xcode 27 からの書き方

alert(error:) に、エラーの Optional の Binding を渡すだけです。

struct ContentView: View {
    @State private var error: SampleLocalizedError?

    var body: some View {
        Button("読み込む") {
            Task {
                do {
                    try await load()
                } catch let error as SampleLocalizedError {
                    self.error = error
                } catch {}
            }
        }
        .alert(error: $error) { _ in
            Button("OK") {}
        } message: { error in
            Text(error.recoverySuggestion ?? "")
        }
    }
}

State はエラーの1つだけになりました。値を代入すると表示されて、閉じると自動で nil に戻ります。Bool の管理がいらないのは地味に嬉しいです。

タイトルには、従来と同じく errorDescription が使われていました。本文は message: で自分で組み立てます。

素のErrorを渡せる

alert(error:) には LocalizedError に準拠していない Error も渡せます。catch で受け取った any Error をそのまま入れられるので、試してみました。

@State private var error: (any Error)?

// ...
catch {
    self.error = error
}

.alert(error: $error) {
    Button("OK") {}
}

タイトルにはエラーの localizedDescription がそのまま出ました。URLError(.notConnectedToInternet) を渡してみたら以下の内容

  • The operation couldn’t be completed. (NSURLErrorDomain error -1009.)

開発者向けの文言なので、ユーザーに見せる画面でそのまま使うのは厳しいな...と感じました(じゃあいつ使うんだろう)
結局実務では LocalizedError に準拠させて文言を決めるケースが多いかなと思います。

任意の値を渡して表示する

従来の書き方

エラー以外の値を渡す alert(_:isPresented:presenting:) も、表示フラグの Bool が必要でした。

@State private var isPresented = false
@State private var target: String?

Button("削除") {
    target = "サンプル"
    isPresented = true
}
.alert("確認", isPresented: $isPresented, presenting: target) { _ in
    Button("OK") {}
} message: { target in
    Text(target)
}

Xcode 27 からの書き方

alert(_:item:) に Optional の Binding を渡します。

@State private var target: String?

Button("削除") {
    target = "サンプル"
}
.alert("確認", item: $target) { _ in
    Button("OK") {}
} message: { target in
    Text(target)
}

こちらも閉じると nil に戻りました。

sheet(item:) は Identifiable への準拠が必要ですが、alert(_:item:) は不要。上のコードのように String をそのまま渡せます。

confirmationDialog(_:item:) にも同じ形のAPIが追加されています。

表示中に値を変えても反映されない

表示中に値を書き換えても、アラートの中身は変わりませんでした。alert(error:) と alert(_:item:) のどちらも同じです。

alert(_:item:) の Apple のドキュメントには、表示後の変更は無視されると書かれています。alert(error:) のドキュメントには記載がありませんが、検証環境(Xcode 27 / iOS 27.0 Simulator)で確認したところ同じ挙動でしたので注意が必要です。

古い OS でも使える

Apple のドキュメントを見ると、alert(error:) と alert(_:item:) の対応 OS は iOS 15.0 以降になっていました

そのため Xcode 27 でビルドすれば、古い OS をサポートしているアプリでも使えます。

ただし、LocalizedError に準拠していない素の Error を渡すAPIはiOS 27 以降でしか使えなさそうです。

まとめ

  • Xcode 27 で alert(error:) と alert(_:item:) が追加された
  • 表示フラグの Bool がいらなくなり、Optional の値を代入するだけで表示できる
  • 閉じると自動で nil に戻るので、後始末のコードもいらない
  • 表示中に値を書き換えても、アラートの中身は変わらない
  • alert(error:) には素の Error も渡せるが、タイトルに開発者向けの文言がそのまま出る
  • alert(_:item:) は sheet(item:) と違って Identifiable が不要
  • Xcode 27 でビルドすれば iOS 15 から使える(素の Error を渡す場合は iOS 27 から)

参考

https://developer.apple.com/documentation/updates/swiftui

https://developer.apple.com/documentation/swiftui/view/alert(error:actions:)

https://developer.apple.com/documentation/swiftui/view/alert(_:item:actions:)

https://developer.apple.com/jp/documentation/swiftui/view/confirmationdialog(_:item:titlevisibility:actions:)

この記事をシェアする

関連記事