是didSet上@约束力的文件具体?

0

的问题

基本上,我在筑巢 @Binding 3层的深度。

struct LayerOne: View {
    @State private var doubleValue = 0.0
    
    var body: some View {
        LayerTwo(doubleValue: $doubleValue)
    }
}

struct LayerTwo: View {
    @Binding var doubleValue: Double {
        didSet {
            print(doubleValue)
        }
    }
    
    var body: some View {
        LayerThree(doubleValue: $doubleValue)
    }
}

struct LayerThree: View {
    @Binding var doubleValue: Double {
        didSet {
            print(doubleValue) // Only this print gets run when doubleValue is updated from this struct
        }
    }

    var body: Some view {
        // Button here changes doubleValue
    }
}

哪种结构改变我 doubleValue 在一个地方的 didSet 会得到运行,因此,举例来说,如果我改变它 LayerThree 只有一个将打印,没有任何其他人。

我能看到的变化与 .onChange(of: doubleValue) 然后将得到运行时,它的变化,但它是不理解我为什么 didSet 不会得到运行,除了对结构,它的改变。

@Binding struct具体?

swift swiftui
2021-11-22 18:09:26
3

最好的答案

1

使用的财产的观察员喜欢 didSet 关于价值观包裹 PropertyWrappers 不会有"正常"效果,因为值正在内部设定的包装。

在SwiftUI,如果你想触发一个行动时,一个价值变化,则应当使用 onChange(of:perform:) 改性剂。

struct LayerTwo: View {
    @Binding var doubleValue: Double
    
    var body: some View {
        LayerThree(doubleValue: $doubleValue)
          .onChange(of: doubleValue) { newValue 
            print(newValue)
          }
    }
}
2021-11-22 18:26:49

抓到你了,所以才喜欢我想...它正在设置自身的结构,它的设置,不通过链。
Joe Scotto
0

现在所有的工作:

struct ContentView: View {
    
    var body: some View {
        
        LayerOne()
        
    }
    
}


struct LayerOne: View {
    
    @State private var doubleValue:Double = 0.0 {
        didSet {
            print("LayerOne:", doubleValue)
        }
    }
    
    var body: some View {
        LayerTwo(doubleValue: Binding(get: { return doubleValue }, set: { newValue in doubleValue = newValue } ))
    }
    
}

struct LayerTwo: View  {
    
    @Binding var doubleValue: Double {
        didSet {
            print("LayerTwo:", doubleValue)
        }
    }
    
    var body: some View {
        
        LayerThree(doubleValue: Binding(get: { return doubleValue }, set: { newValue in doubleValue = newValue } ))
    }
}




struct LayerThree: View  {
    
    @Binding var doubleValue: Double {
        didSet {
            print("LayerThree:", doubleValue) 
        }
    }
    
    var body: some View {
        
        Text(String(describing: doubleValue))
            
        Button("update value") {
            doubleValue = Double.random(in: 0.0...100.0)
        }
        .padding()
    }
    
}

打印结果:

LayerOne:64.58963263686678

LayerTwo:64.58963263686678

LayerThree:64.58963263686678

2021-11-22 18:20:58

但是,为什么你需要通过结合这种方式? 不应该 didSet 让触发无论在哪里结合改变了吗?
Joe Scotto

我想我们不要问为什么或如何,因为这是苹果和封闭源。 为使didSet开始工作,你需要的初始化的结合。
swiftPunk
0

看看为什么发生这种情况,我们可以揭开语法糖的财产包装。 @Binding var doubleValue: Double 翻译:

private var _doubleValue: Binding<Double>
var doubleValue: Double {
    get { _doubleValue.wrappedValue }
    set { _doubleValue.wrappedValue = newValue }
}

init(doubleValue: Binding<Double>) {
    _doubleValue = doubleValue
}

不管你做什么在 didSet 将放在一行 _doubleValue.wrappedValue = newValue. 它应该是很明显为什么当你的更新 doubleValue 在3层, didSetdoubleValue 在2层或1没有得到称为。 他们只是不同的计算。

swiftPunk的解决方案 的工作通过创建一个新的结合,其定者设置的结构是 doubleValue因此叫 didSet:

Binding(get: { return doubleValue }, 
        set: { newValue in doubleValue = newValue }
//                         ^^^^^^^^^^^^^^^^^^^^^^
//                         this will call didSet in the current layer
2021-11-22 18:37:59

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................