@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)
}
}
}
我有一个带有两个轮式选择器的时间选择子视图,一个用于分钟,一个用于秒。这些值绑定到父视图中的两个(本地)状态变量。我正在寻找一种方法,让全局状态变量 "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)
}
}
}