0
1

SwiftUIのalertのためにOptionalを持つBindingの拡張メソッドを作ってみた。

Last updated at Posted at 2023-12-27

SwiftUIでalertをスマートに実装する方法を模索中です。

例えば alert(_:isPresented:presenting:actions:message:) の場合、presentingに与えるデータの有無に連動して、isPresentedのtrue/falseが切り替わる仕組みがあると、便利と思いました。

Bindingには get/setのクロージャで値変換が可能なイニシャライザがあるので、これを利用してみます。

で、汎用的に使えるように拡張メソッドを作ってみました。

extension Binding {
    func bool<T>() -> Binding<Bool> where Value == Optional<T> {
        Binding<Bool> (
            get: {
                self.wrappedValue != nil
            },
            set: { newValue in
                // alertはボタンタップで非表示に変化の時にfalseをsetする。
                // その際には、元のOptional値をnilに更新する。
                if !newValue {
                    self.wrappedValue = nil
                }
                // trueがsetの時は何もしない。
            }
        )
    }
}

alertで利用する場合は、以下のような感じ。

enum AlertKind {
    case hello
    case world
}

struct DemoView: View {

    @State
    var alertKind: AlertKind?

    var body: some View {
        Form {
            Button("hello") {
                alertKind = .hello
            }
            Button("world") {
                alertKind = .world
            }
            Button("state") {
                print("kind: \(String(describing: alertKind))")
            }
        }
        .alert(
            "alert demo",
            isPresented: $alertKind.bool(),
            presenting: alertKind
        ) { kind in
            switch kind {
            case .hello:
                Button("OK") { }
                Button("NG") { }
            case .world:
                Button("OK") { }
            }
        } message: { kind in
            switch kind {
            case .hello:
                Text("hello")
            case .world:
                Text("world")
            }
        }
    }
}

SwiftUI経験がまだ浅いので、他に良い方法があるのかは分かっていませんが。
isPresentedのために、わざわざBoolのプロパティを持つ必要が無くなるので、割とスマートな実装になりそうと思いました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1