SwiftUI:动作不触发与切换



我想用拨动开关触发一个动作。在本例中,打印消息"value "点击按钮后不会在控制台上显示

这是针对macOS 10.15应用程序的,. onchange将无法工作。

struct ContentView: View {
@State private var isToggle : Bool = false {
didSet {
print("value did change")
}
}
var body: some View {
Toggle(isOn: self.$isToggle){
Text("Toggle Label ")
}
}
}

In不应该(至少从来没有以这种方式工作),因为Toggle改变的不是状态本身(通过直接赋值给属性),而是通过绑定包装值…使用而不是

@State private var isToggle : Bool = false
var body: some View {
Toggle(isOn: self.$isToggle){
Text("Toggle Label ")
}
.onChange(of: isToggle) { _ in
print("value did change")   // << here !!
}
}

我要无耻地窃取@Asperi的答案的第一部分,但第二部分是我的…

@State private var isToggle : Bool = false
var body: some View {
Toggle(isOn: self.$isToggle.onUpdate({
print("value did change")   // << here !!
})){
Text("Toggle Label ")
}
}
extension Binding {

/// Adds a modifier for this Binding that fires an action when a specific
/// value changes.
///
/// You can use `onUpdate` to trigger a side effect as the result of a
/// `Binding` value changing.
///
/// `onUpdate` is called on the main thread. Avoid performing long-running
/// tasks on the main thread. If you need to perform a long-running task in
/// response to `value` changing, you should dispatch to a background queue.
///
/// The new value is NOT passed into the closure.
///
///     struct PlayerView: View {
///         var episode: Episode
///         @State private var playState: PlayState = .paused
///
///         var body: some View {
///             VStack {
///                 Text(episode.title)
///                 Text(episode.showTitle)
///                 PlayButton(playState: $playState.updated {
///                     model.playStateDidChange.update()
///                 })
///             }
///         }
///     }
///
/// - Parameters:
///   - action: A closure to run when the value changes.
///
/// - Returns: A new binding value.
func onUpdate(_ action: @escaping () -> Void) -> Binding<Value> {
Binding(get: {
wrappedValue
}, set: { newValue in
wrappedValue = newValue
action()
})
}
}
extension Binding {
/// Adds a modifier for this Binding that fires an action when a specific
/// value changes.
///
/// You can use `updated` to trigger a side effect as the result of a
/// `Binding` value changing.
///
/// `updated` is called on the main thread. Avoid performing long-running
/// tasks on the main thread. If you need to perform a long-running task in
/// response to `value` changing, you should dispatch to a background queue.
///
/// The new value is passed into the closure.
///
///     struct PlayerView: View {
///         var episode: Episode
///         @State private var playState: PlayState = .paused
///
///         var body: some View {
///             VStack {
///                 Text(episode.title)
///                 Text(episode.showTitle)
///                 PlayButton(playState: $playState.updated { newState in
///                     model.playStateDidChange(newState)
///                 })
///             }
///         }
///     }
///
/// - Parameters:
///   - action: A closure to run when the value changes.
///
/// - Returns: A new binding value.
func updated(_ action: @escaping (_ value: Value) -> Void) -> Binding<Value> {
Binding(get: {
wrappedValue
}, set: { newValue in
wrappedValue = newValue
action(newValue)
})
}
}

有两个绑定扩展可以在iOS 13、watchOS 6和macOS 10中使用。第一个.onUpdate()在绑定值发生变化时触发,但不允许访问旧值或新值。这只是为了防止副作用。我使用上面的这个值只是因为print()不需要任何其他值。

如果您需要在闭包中使用newValue,请使用.updated。它的工作原理与.onChange(of:)非常相似,除了它修改了Binding,并且不允许您访问旧值。

相关内容

  • 没有找到相关文章

最新更新