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

时间:2019-11-25 09:51:07

标签: swiftui combine

我有一个时间选择子视图,其中有两个车轮选择器,一个用于分钟,一个用于秒。这些值绑定到父视图中的两个(局部)状态变量。我正在寻找一种方法,当两个局部变量之一发生更改时,全局状态变量“时间”将每次更改。我不想直接将两个状态变量(以分钟/秒的形式)绑定到全局状态,因为我只想在那里保留一个以秒为单位的时间的变量。因此应该有一个转换时间= min * 60 +秒。

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

这是子视图:

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()
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您可以在主视图中使用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 = $0 * 60 + $1
                    print(self.myTime)
                }
            }
        }

答案 1 :(得分:0)

我认为您需要包装全局变量kind

    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())

很遗憾,没有机会进行测试