为什么didSet在SwiftUI中使用Binding属性时不能按预期工作



在子视图中有以下两个属性:

  1. 是初始化为false的local@State var localValue
  2. 是由父视图切换的@Binding var parentValue属性

我想在代码中使用localValue,因为它开始时为false,然后在初始化视图时切换为true,这将启动一个需要以false开始的动画。parentValue属性在父视图中切换,我希望这能更新我的localValue属性以正确控制动画。尽管parentValue确实在切换,但localValue属性似乎并没有随着didSet而改变。我缺少什么???

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

根据评论更新更多详细信息

如果因为@Binding包装器本身没有改变,所以没有触发didSet,所以没有办法做到这一点,那么我需要的是类似的。

我希望有一个最初设置为false但可以从外部视图切换的属性,以便控制子视图中的动画,该动画会根据切换的值更改方向。

如果我可以将子视图中的绑定属性初始化为false,即如果有某种方法可以设置

@Binding var breath: Bool = false 

作为起始值,则每次父视图切换parentValue属性时,子视图都会正确响应。现在,父视图调用该属性设置为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)

请参阅上面的代码,了解为什么当视图开始时,动画的比例因子为0.2,但在持续时间到期且呼吸属性切换为false时,动画会在反转之前增长到完全大小,这一点很重要。

没有调用didSet的原因是因为属性的值没有更改。您必须为基础_parentValue属性分配一个新的Binding。相反,您可以定义一个新的Binding属性,该属性对parentValue属性进行变异并调用自定义闭包。一个简单的方法是定义一个扩展方法,如下所示:

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

然后,当您初始化属性时,您可以执行以下操作:

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

最新更新