
【SwiftUI】 Xcode 27 でアラートが Bool なしで出せるようになった
はじめに
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 から)
参考










