💡
[SwiftUI]複数のアラートを表示させる
Alertの複数表示
- たまに忘れてしまって焦るが、
Alert
は複数記述すると、後に書いたものに上書きされてしまい、最後のもの以外は反応しなくなる - 下記のサンプルのケースでは、「Button 2」はアラートが表示されるが、「Button 1」はボタンを押しても何も起こらない
struct ContentView: View {
@State var isPresentingWarning = false
@State var isPresentingFatal = false
var body: some View {
NavigationView {
VStack {
Button(action: {
isPresentingWarning.toggle()
}) {
Text("Button 1")
}
.padding()
Button(action: {
isPresentingFatal.toggle()
}) {
Text("Button 2")
}
.padding()
Spacer()
}
}
.alert(isPresented: $isPresentingWarning) {
Alert(title: Text("Warning......"),
dismissButton: .default(Text("OK")))
}
.alert(isPresented: $isPresentingFatal) {
Alert(title: Text("Fatal Error."),
dismissButton: .default(Text("OK")))
}
}
}
動的に読み分ける
- 対応はいくつかあるが、必要なアラートのタイプを
enum
などに定義しておき、alert
の中で読み分ける方法が分かりやすい
struct ContentView: View {
enum AlertType {
case warning
case fatal
}
@State var isPresentingAlert = false
@State var alertType: AlertType = .warning
var body: some View {
NavigationView {
VStack {
Button(action: {
alertType = .warning
isPresentingAlert.toggle()
}) {
Text("Button 1")
}
.padding()
Button(action: {
alertType = .fatal
isPresentingAlert.toggle()
}) {
Text("Button 2")
}
.padding()
Spacer()
}
}
.alert(isPresented: $isPresentingAlert) {
switch alertType {
case .warning:
return Alert(title: Text("Warning......"),
dismissButton: .default(Text("OK")))
case .fatal:
return Alert(title: Text("Fatal Error."),
dismissButton: .default(Text("OK")))
}
}
}
}
ViewModifierにする
- 下記のように、
ViewModifier
にタイプとそれに応じたアラートの挙動を定義し、View
からはそのViewModifier
を呼び出せば良いようにしておくと便利
struct CustomAlert: ViewModifier {
enum AlertType {
case warning(message: String?)
case fatal(message: String?)
}
@Binding var isPresentingAlert: Bool
let type: AlertType
func body(content: Content) -> some View {
content.alert(isPresented: $isPresentingAlert) {
switch type {
case let .warning(message):
return Alert(title: Text("Warning"),
message: Text(message ?? ""),
dismissButton: .default(Text("OK")))
case let .fatal(message):
return Alert(title: Text("Fatal Error."),
message: Text(message ?? ""),
dismissButton: .default(Text("OK")))
}
}
}
}
extension View {
func customAlert(isPresentingAlert: Binding<Bool>, type: CustomAlert.AlertType) -> some View {
modifier(CustomAlert(isPresentingAlert: isPresentingAlert, type: type))
}
}
struct ContentView: View {
@State var isPresentingAlert = false
@State var alertType: CustomAlert.AlertType = .warning(message: nil)
private let warningMessage = ""
private let fatalErrorMessage = ""
var body: some View {
NavigationView {
VStack {
Button(action: {
alertType = .warning(message: warningMessage)
isPresentingAlert.toggle()
}) {
Text("Button 1")
}
.padding()
Button(action: {
alertType = .fatal(message: fatalErrorMessage)
isPresentingAlert.toggle()
}) {
Text("Button 2")
}
.padding()
Spacer()
}
}
.customAlert(isPresentingAlert: $isPresentingAlert,
type: alertType)
}
}
reference: https://capibara1969.com/2758/
Discussion