DidSet bir @ Binding dosyasına özgü mü?

0

Soru

Esasen yuvalıyorum. @Binding 3 kat derinliğinde.

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
    }
}

Hangi yapıyı değiştirirsem doubleValue içinde bir tane var didSet çalıştırılacak, örneğin değiştirirsem LayerThree sadece biri basacak, diğerleri basmayacak.

Değişiklikleri izleyebiliyorum .onChange(of: doubleValue) o zaman değiştiğinde kaçacak ama neden bana mantıklı gelmiyor didSet değiştirildiği yapı dışında çalıştırılmayacak.

Oluyor @Binding yapıya özgü mü?

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

En iyi cevabı

1

Aşağıdaki gibi özellik gözlemcilerini kullanma didSet sarılmış değerler üzerinde PropertyWrappers değer sarıcı içinde ayarlandığından "normal" etkisi olmaz.

Swiftui'de, bir değer değiştiğinde bir eylemi tetiklemek istiyorsanız, aşağıdakileri kullanmalısınız: onChange(of:perform:) değiştirici.

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

Anladım, tam düşündüğüm gibi... set up zinciri yoluyla değil bu yapı içinde ayarlanan bir şey.
Joe Scotto
0

Şimdi her şey çalışıyor:

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()
    }
    
}

baskı sonuçları:

Katman: 64.58963263686678

Katman iki: 64.58963263686678

Katmanüç: 64.58963263686678

2021-11-22 18:20:58

Ama neden bağlamayı bu şekilde geçmen gerekiyor? Olmamalı didSet bağlamanın nerede değiştirildiğine bakılmaksızın tetiklenir mi?
Joe Scotto

Sanırım neden ve nasıl olduğunu soramayız, çünkü Apple ve kapalı kaynak. Didset'in çalışmaya başlaması için Bağlama için başlatmaya ihtiyacınız vardır.
swiftPunk
0

Bunun neden olduğunu görmek için, özellik paketleyicilerinin sözdizimsel şekerini açıklayabiliriz. @Binding var doubleValue: Double çevirir:

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

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

Ne olursa olsun didSet satırdan sonra konacak _doubleValue.wrappedValue = newValue. Güncelleme yaparken neden çok açık olmalı doubleValue katman 3'te, didSet -den doubleValue katman 2 veya 1'de çağrılmaz. Bunlar sadece farklı hesaplanmış özelliklerdir!

Swiftpunk'un çözümü, ayarlayıcısı yapıyı ayarlayan yeni bir bağlama oluşturarak çalışır. doubleValue dolayısıyla arama didSet:

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

Diğer dillerde

Bu sayfa diğer dillerde

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