简体   繁体   English

为什么 didSet 在 SwiftUI 中使用 Binding 属性无法按预期工作

[英]Why is didSet not working as expected with a Binding property in SwiftUI

I have the following two properties in a child view:我在子视图中有以下两个属性:

  1. is a local @State var localValue that is initialized to false是初始化为 false 的本地 @State var localValue
  2. is a @Binding var parentValue property that is being toggled by a parent view.是由父视图切换的 @Binding var parentValue 属性。

I want to use the localValue in my code since it starts out false and then is toggled to true when the view is initialized and this starts an animation that needs to start out as false.我想在我的代码中使用 localValue,因为它以 false 开始,然后在视图初始化时切换为 true,这将启动一个需要以 false 开始的动画。 The parentValue property gets toggled in the parent view and I want this to update my localValue property to control the animation properly. parentValue 属性在父视图中被切换,我希望它更新我的 localValue 属性以正确控制动画。 Although the parentValue is indeed toggling the localValue property does not seem to be changing with the didSet.尽管 parentValue 确实在切换 localValue 属性,但似乎没有随 didSet 改变。 What am I missing???我错过了什么???

@State var localValue = false

@Binding var parentValue: Bool {
    didSet {localValue = parentValue}
}

Update with more detail based on comment根据评论更新更多细节

If there is no way to do this because the @Binding wrapper itself is not changing so didSet is not being triggered then what I need is similar.如果没有办法做到这一点,因为@Binding 包装器本身没有改变所以 didSet 没有被触发,那么我需要的是类似的。

I would like to have a property that is initially set to false but that can be toggled from an external view so as to control an animation in the child view which changes direction based on the value being toggled.我想要一个最初设置为 false 但可以从外部视图切换的属性,以便控制子视图中的动画,该动画根据被切换的值改变方向。

If I could initialize the bound property in the child view to false ie if there was some way to set如果我可以将子视图中的绑定属性初始化为 false 即是否有某种方法可以设置

@Binding var breath: Bool = false 

as the starting value then each time the parent toggles the parentValue property the child view would respond properly.作为起始值,每次父视图切换 parentValue 属性时,子视图都会正确响应。 As it is now the parent view calls the child view with this property set to true which means the animation is fully expanded whereas I want the first step to have the animation grow for a particular duration and then reverse when the parent sets the value to false for some other duration amount.现在父视图调用子视图并将此属性设置为 true,这意味着动画已完全展开,而我希望第一步让动画在特定持续时间内增长,然后在父视图将值设置为 false 时反转对于其他一些持续时间。

    // Whole flower
                .rotationEffect(.degrees(breath ? 360 : 0), anchor: .center) // Inhale = clockwise rotation, Exhale = anticlockwise rotation
                .scaleEffect(breath ? 1 : 0.2) // Inhale = upscale, Exhale = downscale
                .animation( Animation.easeInOut(duration: self.stepDuration))
                .opacity(breath ? 1 : 0.75)

See the code above for why it is important that when the view starts the animation is at a scale factor of 0.2 but then grows to full size before reversing when the duration has expired and the breath property has been toggled to false.请参阅上面的代码,了解为什么当视图开始时动画的比例因子为 0.2,但在持续时间到期且呼吸属性已切换为 false 时在反转之前增长到全尺寸很重要。

The reason didSet is not called is because the property's value is not changed. didSet没有被调用的原因是因为属性的值没有改变。 You would have to assign a new Binding to the underlying _parentValue property.您必须为基础_parentValue属性分配一个新的Binding Instead, you can define a new Binding property that mutates the parentValue property and calls a custom closure.相反,您可以定义一个新的Binding属性来改变parentValue属性并调用自定义闭包。 An easy way to do this is to define an extension method like this:一个简单的方法是定义一个扩展方法,如下所示:

extension Binding {
    func didSet(_ closure: @escaping (Value) -> ()) -> Binding<Value> {
        Binding(
            get: { self.wrappedValue },
            set: {
                self.wrappedValue = $0
                closure($0)
            }
        )
    }
}

Then when you initialize your property, you can do something like:然后当您初始化您的财产时,您可以执行以下操作:

self.parentValue = $someBinding.didSet { localValue = $0 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM