Czy didSet specyficzne dla pliku @Binding?

0

Pytanie

W rzeczywistości, ja гнездюсь @Binding 3 warstwy w głąb.

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

Jaką strukturę nie zmienił doubleValue w tym, gdzie znajduje się didSet zostanie uruchomiony, tak, że, na przykład, jeśli zmienię go w LayerThree tylko ten zostanie wydrukowany, żaden z pozostałych nie będzie.

Mogę śledzić zmiany za pomocą .onChange(of: doubleValue) który następnie zostanie uruchomiony, gdy on się zmieni, ale dla mnie to nie ma sensu, dlaczego didSet nie będzie działać, chyba, że w strukturze, w której został zmieniony.

Jest @Binding konkretna struktura?

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

Najlepsza odpowiedź

1

Korzystanie z obserwatorów właściwości, takich jak didSet o wartościach, owiniętych w PropertyWrappers nie będzie mieć "normalnego" efektu, ponieważ wartość ta jest ustawiana wewnątrz skorupy.

W SwiftUI, jeśli chcesz zainicjować akcję po zmianie wartości, należy użyć onChange(of:perform:) modyfikator.

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

Mam cię, tak, jak myślałem... jest instalowany wewnątrz struktury, w której jest zamontowany, a nie na łańcuchu.
Joe Scotto
0

Teraz wszystko działa:

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

wyniki drukowania:

LayerOne: 64,58963263686678

Dwie warstwy: 64.58963263686678

Trzy warstwy: 64,58963263686678

2021-11-22 18:20:58

Ale dlaczego trzeba wysyłać powiązanie w ten sposób? Nie musi didSet wyzwalana jest zawsze, niezależnie od tego, gdzie zmieniona przyciąganie?
Joe Scotto

Myślę, że nie możemy pytać, dlaczego i jak, bo to Apple i zamknięty kod źródłowy. Aby didSet zaczął działać, potrzebna jest inicjacja do wiązania.
swiftPunk
0

Aby zrozumieć, dlaczego tak się dzieje, możemy ujawnić cukier syntaktyczny śluzowych właściwości. @Binding var doubleValue: Double tłumaczy się jako:

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

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

Cokolwiek robisz w didSet będzie wystawiona po linie _doubleValue.wrappedValue = newValue. Powinno być oczywiste, dlaczego po aktualizacji doubleValue w warstwie 3, didSet od doubleValue w warstwie 2 lub 1 nie jest wywoływana. To po prostu różne obliczeniowe właściwości!

Rozwiązanie swiftPunk działa poprzez stworzenie nowej przyciągania, instalator której określa strukturę doubleValuedlatego, powodując didSet:

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

W innych językach

Ta strona jest w innych językach

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