简体   繁体   English

面对 State 的一些奇怪行为或 SwiftUI 中的 didSet 情况下的绑定

[英]Facing with some strange behaviour of State or Binding in didSet situation in SwiftUI

I am updating my State variable with a Binding from another View, I have some code in didSet of my State, it would fired when I do set value from State, but not from Binding, for this reason I have to give a didSet to Binding of this State, which is not logical for me, Binding should Bind but it makes own version of that value with this advantage of updating State as well, I was wandering if it is a bug or it should be in this way, I mean I am expecting reference type behaviour in term of State-Binding, but with this down code? I am updating my State variable with a Binding from another View, I have some code in didSet of my State, it would fired when I do set value from State, but not from Binding, for this reason I have to give a didSet to Binding这个 State,这对我来说不合逻辑,绑定应该绑定,但它使用更新 State 的优势创建了该值的自己版本,我在徘徊,如果它是一个错误,或者它应该以这种方式,我的意思是我我期待在状态绑定方面的引用类型行为,但是使用这个向下代码? it shows more like Value type!它显示更像值类型! Why this is happening?为什么会这样? I was expecting didSet of State get fired even update coming from Binding!我期待 State 的 didSet 即使来自 Binding 的更新也会被解雇!

    import SwiftUI

struct ContentView: View {
    
    @State var someProperty: String = "Empty string!" {
        
        didSet(oldValue) {
            
            print("State didSet → " + someProperty)
            
        }
    }
    
    var body: some View {
        
        Text(someProperty)
            .padding()
        
        ButtonView(someProperty: $someProperty)
        
    }
}


struct ButtonView: View {
    
    @Binding var someProperty: String  {
        
        didSet(oldValue) {
            
            print("Binding didSet → " + someProperty)
            
        }
    }
    
    var body: some View {
        
        Button("update Text") { someProperty = "Hello, world!" }
        
    }
}

update:更新:

    struct ContentView: View {

    @State private var someProperty: String = "Empty string!" {

        didSet(oldValue) {

            print("State didSet → " + someProperty)

        }
    }

    var body: some View {

        Text(someProperty)
            .padding()

        Button("update Text") { someProperty = "Hello, world!" }


    }
}

Use custom binding使用自定义绑定

var body: some View {
    
    Text(someProperty)
        .padding()
    
    ButtonView(someProperty: Binding(
        get: { self.someProperty },
        set: { self.someProperty = $0 }
    ))
    
}

didSet works with @State only when you modify the @State directly but not when you change its internal value. didSet仅在您直接修改@State而不是在您更改其内部值时才与@State一起使用。

Note that the State is a wrapper .请注意, State是一个包装器 If you change its internal value (here _someProperty ) using Binding , then didSet is not called.如果您使用Binding更改其内部值(此处_someProperty ),则不会调用didSet

You can use onReceive or onChange instead:您可以使用onReceiveonChange代替:

import Combine
import SwiftUI

struct ContentView: View {
    @State private var someProperty: String = "Empty string!"

    var body: some View {
        Text(someProperty)
            .padding()
            // updated on changes only
            .onChange(of: someProperty) {
                print("State onChange → " + $0)
            }
            // updated every time
            .onReceive(Just(someProperty)) {
                print("State onReceive → " + $0)
            }

        ButtonView(someProperty: $someProperty)
    }
}

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

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