【SwiftUI 3.0】alert プロパティでアラートダイアログを表示する

SwiftUI 3.0 で Alertdeprecated になりました。

そのため、alert プロパティの各種引数を利用することで色々なタイプのアラートダイアログを出すような仕様に変更されました。

一通りの使い方について紹介していきます。

動作確認済環境

MacOS Monterey(12.0.1)

Xcode 13.1

iOS 15.0

iPhone 13 mini シミュレータ

【SwiftUI 3.0】alert プロパティでアラートダイアログを表示する

alert の使い方を確認

Binding<Bool> 型の状態変数(@State or @Published)を宣言し、alert プロパティの isPresented: 引数に指定します。

ボタンなどで true にすることでアラートを表示できます。

struct ContentView: View {
    @State var isShowAlert = false
    var body: some View {
        VStack {
            Button(action: {
                isShowAlert = true
            }, label: {
                Text("Show Alert")
            })
        }
        .alert("アラート", isPresented: $isShowAlert, actions: {})
    }
}

よく使うinit(イニシャライザ)のパターン

①OKボタンのみ

actions: の中身を指定しない場合は OK ボタンがデフォルトで表示されます。

.alert("OKアラート", isPresented: $isShowAlert, actions: {})

②任意のボタンのみ

actions: には任意のボタンを設置できます。

.alert("アラート", isPresented: $isShowAlert, actions: {
    Button(action: {
        print("Tap!")
    }, label: {
        Text("確認")
    })
})

③メッセージ付きアラート

message: に Text をセットするとタイトルの下にメッセージテキストを表示できます。

.alert("メッセージ付きアラート", isPresented: $isShowAlert, actions: {}, message: {
    Text("詳しい内容ですよ")
})

④エラーアラート

LocalizedError プロトコルに準拠した独自のエラーを定義し、それをアラートに渡して利用することもできます。

例として、WebAPIのレスポンスのエラーを enum で定義してみました。

enum ApiError: LocalizedError {
    case networkError
    case emailIncorrectFormat
    case wrongPassword
    
    var errorDescription: String? {
        switch self {
        case .networkError:
            return "ネットワークエラー"
        case .emailIncorrectFormat:
            return "メールアドレスの形式が誤っています"
        case .wrongPassword:
            return "パスワードが間違っています"
        }
    }
    
    var failureReason: String? {
        switch self {
        case .networkError:
            return "通信エラーです。少し時間をおいてから再度お試しください。"
        case .emailIncorrectFormat:
            return "入力されたメールアドレスの形式が不正です。入力内容をお確かめください。"
        case .wrongPassword:
            return "登録しているパスワードと一致しません。入力内容をお確かめください。"
        }
    }
}

var errorDescription: String?var failureReason: String? を実装しないと LocalizedError に準拠したことにならないので注意してください。

実際にAPIを投げて受け取るところは今回は割愛させて頂きますが、受け取ったエラーを @State or @Published の変数に保持し、アラートを表示するパターンは以下のようになります。

struct ContentView: View {
    @State var isShowAlert = false
    @State var apiError: ApiError = .networkError
    
    var body: some View {
        VStack {
            Button(action: {
                isShowAlert = true
            }, label: {
                Text("Show Alert")
            })
        }
        .alert(isPresented: $isShowAlert, error: apiError, actions: { error in
            Button("OK", action: {})
        }, message: { error in
            Text(apiError.failureReason ?? "予期しないエラーです。")
        })
    }
}

apiError に入っている enum の値によって errorDescriptionfailureReason出し分けることができます

以上、SwiftUI 3.0 で仕様が変わった alert の表示方法について紹介しました。3.0 になってから漸く SwiftUI もまとまって来たかなと言う印象です。

いよいよ UIKit からの卒業も近い?