[SwiftUI]複数ダイアログを表示する

目次

概要

SwiftUIでダイアログを表示する。
ダイアログ表示には「.alert」や「Alertクラス」を使えば良いが、「.alert」は複数実装すると動作しないため、それも含めてメモ

ソースコード

import SwiftUI

@main
struct TestApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ShowAlertView()
        }
    }
}

View表示部分

import SwiftUI

struct ShowAlertView: View {
    @ObservedObject var viewModel: ShowAlertViewModel = ShowAlertViewModel()
    
    var body: some View {
        ZStack {
            VStack {
                Spacer()
                Button {
                    self.viewModel.isDefaultDialogPresented = true
                } label: {
                    Text("閉じるボタンのみのアラートを表示する")
                }
                Spacer()
                Button {
                    self.viewModel.isDeleteDialogPresented = true
                } label: {
                    Text("削除ボタンのアラートを表示する")
                }
                Spacer()
            }
            dialogView()
        }
    }
    
    private func dialogView() -> some View {
        return ZStack {
            Text("")
                .alert(isPresented: self.$viewModel.isDefaultDialogPresented) {
                    Alert(title: Text("閉じるボタンのみアラート表示のタイトル"),
                          message: Text("閉じるボタンのみアラート本文"),
                          dismissButton: .default(Text("閉じる")) {
                        print("閉じます")
                    })
                }
            Text("")
                .alert(isPresented: self.$viewModel.isDeleteDialogPresented) {
                    Alert(title: Text("削除アラート表示のタイトル"),
                          message: Text("削除アラート本文"),
                          primaryButton: .cancel(Text("キャンセル")) {
                        print("キャンセルします")
                    },
                          secondaryButton: .destructive(Text("削除")) {
                        print("削除します")
                    })
                }
        }
    }
}

処理部分

import Foundation

class ShowAlertViewModel: ObservableObject {
    @Published var isDefaultDialogPresented = false
    @Published var isDeleteDialogPresented = false
}

デモ動画

詳細

ダイアログを表示する際は、Alertを使用する。
それぞれのプロパティは以下のような感じ。

Alertのプロパティ内容

プロパティ名用途
titleダイアログのタイトルを表示する。
ダイアログの上部に表示されて太文字になる。
messageダイアログの本文を表示する。
ダイアログのタイトルの下に表示されて、文字の太さは通常。
dismissButtonボタンの数が一つのダイアログを表示させる場合はこちらを使う。
primaryButtonボタンの数が二つのダイアログを表示させる。
こちらは左側に表示するボタン。
secondaryButtonボタンの数が二つのダイアログを表示させる。
こちらは右側に表示するボタン。

また、ボタンの種類も以下のように分類される。

Alertのボタンの種類

ボタンの種類内容
.default通常のボタン。特に特筆することはない。
.cancel太文字のボタンになる。
処理をしようとして、「やっぱりやめたい」という時に使われることが多い。
.destructive赤文字のボタンになる。
設定アプリで初期化をする際など、何かのデータを削除する時に使われることが多い。

今回はZstackの内に「Text(“”)」を設定しているスタイルをとっている。
これは、「.alert(isPresented:)」を複数書くと最後に書かれたものしか有効にならないため。
.alert(isPresented:)」を一つしか書かないなら、わざわざ「Text(“”)」を書く必要はない。
Modelクラスでメッセージを修正するとか、返すアラートの内容を分岐させるとか、色々やりようはある。
ただ、今回は「後から見てわかりやすい」をコンセプトに書いている。