web-dev-qa-db-ja.com

swiftUI toggle()がトグルされたときにアクションをトリガーするにはどうすればよいですか?

SwiftUIビューでは、Toggle()が状態を変更したときにアクションをトリガーする必要があります。トグル自体はバインディングのみを受け取ります。したがって、@ State変数のdidSetでアクションをトリガーしようとしました。しかし、didSetが呼び出されることはありません。

アクションをトリガーする(他の)方法はありますか?または、@ State変数の値の変化を観察する方法はありますか?

私のコードは次のようになります:

struct PWSDetailView : View {

    @ObjectBinding var station: PWS
    @State var isDisplayed: Bool = false {
        didSet {
            if isDisplayed != station.isDisplayed {
                PWSStore.shared.toggleIsDisplayed(station)
            }
        }
    }

    var body: some View {
            VStack {
                ZStack(alignment: .leading) {
                    Rectangle()
                        .frame(width: UIScreen.main.bounds.width, height: 50)
                        .foregroundColor(Color.lokalZeroBlue)
                    Text(station.displayName)
                        .font(.title)
                        .foregroundColor(Color.white)
                        .padding(.leading)
                }

                MapView(latitude: station.latitude, longitude: station.longitude, span: 0.05)
                    .frame(height: UIScreen.main.bounds.height / 3)
                    .padding(.top, -8)

                Form {
                    Toggle(isOn: $isDisplayed)
                    { Text("Wetterstation anzeigen") }
                }

                Spacer()
            }.colorScheme(.dark)
    }
}

望ましい動作は、Toggle()が状態を変更したときにアクション「PWSStore.shared.toggleIsDisplayed(station)」がトリガーされることです。

7
Brezentrager

まず、station.isDisplayedの追加のKVO通知が問題であることを実際に知っていますか?パフォーマンスの問題が発生していますか?そうでない場合は、心配する必要はありません。

パフォーマンスの問題が発生していて、それらが過度のstation.isDisplayed KVO通知によるものであることが判明した場合、次に試すことは、不要なKVO通知を排除することです。これは、手動のKVO通知に切り替えることによって行います。

このメソッドをstationのクラス定義に追加します。

@objc class var automaticallyNotifiesObserversOfIsDisplayed: Bool { return false }

また、SwiftのwillSetおよびdidSetオブザーバーを使用して、手動でKVOオブザーバーに通知しますが、値が変化している場合のみです。

@objc dynamic var isDisplayed = false {
    willSet {
        if isDisplayed != newValue { willChangeValue(for: \.isDisplayed) }
    }
    didSet {
        if isDisplayed != oldValue { didChangeValue(for: \.isDisplayed) }
    }
}
0
rob mayoff
class PWSStore : ObservableObject {
    ...
    var station: PWS
    @Published var isDisplayed = true {
        willSet {
            PWSStore.shared.toggleIsDisplayed(self.station)
        }
    }   
}

struct PWSDetailView : View {
    @ObservedObject var station = PWSStore.shared
    ...

    var body: some View {
        ...
        Toggle(isOn: $isDisplayed) { Text("Wetterstation anzeigen") }
        ...
    }   
}

デモはこちら https://youtu.be/N8pL7uTjEFM

1