@State 变量改变时如何调用函数

How to call a function when a @State variable changes

我有一个带有两个轮式选择器的时间选择子视图,一个用于分钟,一个用于秒。这些值绑定到父视图中的两个(本地)状态变量。我正在寻找一种方法,让全局状态变量 "time" 每次在两个局部变量中的任何一个发生变化时都发生变化。我不想直接将 min/sec 的两个状态变量绑定到全局状态,因为我只希望其中一个变量以秒为单位保存时间。所以应该有一个转换时间 = min * 60 + seconds.

我正在努力寻找一种方法来检测两个局部状态变量的值变化。

这是子视图:

struct TimePicker: View {
    var min: Binding<Int>
    var sec: Binding<Int>

    var body: some View {
        HStack() {
            Spacer()
            Picker(selection: min, label: EmptyView()) {
                ForEach((0...9), id: \.self) { ix in
                    Text("\(ix)").tag(ix)
                }
            }.frame(width: 40).clipped().pickerStyle(WheelPickerStyle())
            Text("Min.")
            Picker(selection: sec, label: EmptyView()) {
                ForEach((0...59), id: \.self) { ix in
                    Text("\(ix)").tag(ix)
                }
            }.frame(width: 40).clipped().pickerStyle(WheelPickerStyle())
            Text("Sec.")
            Spacer()
        }
    }
}

我认为你需要包装你的全局变量

    class TimeObject : BindableObject {
    let didChange = PassthroughSubject<Void, Never>()

    var time:Int = 0 {
        didSet {
            didChange.send(())
        }
    }
}

...

  struct TimePicker: View {
    var min: Binding<Int>
    var sec: Binding<Int>
    @EnvironmentObject var time : TimeObject
    var body: some View {
        HStack() {
            Spacer()
            Picker(selection: min, label: EmptyView()) {
                ForEach((0...9), id: \.self) { ix in
                    Text("\(ix)").tag(ix)
                }.gesture(TapGesture().onEnded(){
                        time.time = ix
                })
            }.frame(width: 40).clipped().pickerStyle(WheelPickerStyle())
            Text("Min.")
            Picker(selection: sec, label: EmptyView()) {
                ForEach((0...59), id: \.self) { ix in
                    Text("\(ix)").tag(ix)
                }.gesture(TapGesture().onEnded(){
                        time.time = ix
                })
            }.frame(width: 40).clipped().pickerStyle(WheelPickerStyle())
            Text("Sec.")
            Spacer()
          }
       }
     }

...

TimePicker..environmentObject(TimeObject())

可惜没机会测试

您可以在主视图中使用 combineLatest。

               struct MainTimeView: View{
            @State private var min : Int = 0
            @State private var sec : Int = 0

           @State private var myTime: Int = 0
             var body: some View {

                TimePicker(min: $min, sec: $sec).onReceive(Publishers.CombineLatest(Just(min), Just(sec))) {
                    self.myTime = [=10=] * 60 + 
                    print(self.myTime)
                }
            }
        }