はじめに
iOSDCで「SwiftUIのハマりどころと回避策」を拝見して自分的にはこうすると思った事があったので記事にしておきます。
アラートのバグ
1つのViewに対して2つのアラートを適用している場合に外側のアラートしか表示されないバグです。
iOS14
import SwiftUI
struct ContentView: View {
@State private var isAlert1 = false
@State private var isAlert2 = false
var body: some View {
VStack(alignment: .center, spacing: 30) {
Button("アラート1") {
isAlert1 = true
}
Button("アラート2") {
isAlert2 = true
}
}
.alert(isPresented: $isAlert1) {
Alert(title: Text("アラート1"))
}
.alert(isPresented: $isAlert2) {
Alert(title: Text("アラート2"))
}
}
}
上記のコードの場合、
アラート2は表示されて、アラート1は表示されません。
回避策
UIAlertControllerを使用します。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(alignment: .center, spacing: 30) {
Button("アラート3") {
alert(title: "アラート", message: nil, buttons: [
UIAlertAction(title: "OK", style: .default)
])
}
}
}
private func alert(title: String?, message: String?, buttons: [UIAlertAction]? = nil) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
if let buttons = buttons {
for button in buttons {
alert.addAction(button)
}
}
UIApplication.shared.windows.first?.rootViewController?.present(alert, animated: true, completion: nil)
}
}
使い方
ボタンを増やすには配列の中にUIAlertAction
を追加していきます
alert(title: "アラート", message: nil, buttons: [
UIAlertAction(title: "キャンセル", style: .cancel),
UIAlertAction(title: "OK", style: .default)
])
おわり
iOS15からはこちらのやり方でアラートを実装することでこのバグを回避する事ができます。
しかし、最低OSがiOS15になるのはまだ先になると思うので、
しばらくは回避策を使うことになりそうです