Est didSet sur un @de Liaison de fichier spécifique?

0

La question

Essentiellement, je suis de nidification @Binding 3 niveaux de profondeur.

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

Selon struct-je changer doubleValue dans l'est de l'endroit où l' didSet allez vous faire, si par exemple je l'ai changer en LayerThree seulement que l'on va imprimer, aucun des autres.

Je suis en mesure de surveiller les modifications apportées à .onChange(of: doubleValue) qui seront ensuite courir quand il change, mais il ne fait pas de sens pour moi pourquoi didSet ne pas se faire rouler, sauf sur la structure où il est modifié à partir de.

Est @Binding struct spécifique?

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

La meilleure réponse

1

En utilisant la propriété des observateurs comme didSet sur les valeurs enveloppé dans PropertyWrappers n'aura pas la "normale" effet parce que la valeur est définie à l'intérieur de l'emballage.

Dans SwiftUI, si vous voulez déclencher une action lors de la modification d'une valeur, vous devez utiliser la onChange(of:perform:) modificateur.

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

Gotcha, donc, juste comme je le pensais... il est défini à partir de la structure que c'est mis, non pas par le biais de la chaîne.
Joe Scotto
0

Maintenant, tous les de travail:

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

imprimer les résultats:

LayerOne: 64.58963263686678

LayerTwo: 64.58963263686678

LayerThree: 64.58963263686678

2021-11-22 18:20:58

Mais pourquoi avez-vous besoin de passer de la liaison de cette façon? Ne devrait pas didSet obtenir déclenchée indépendamment de l'endroit où la liaison est changé?
Joe Scotto

Je pense que nous ne pouvons pas demander pourquoi, ou comment, parce que c'est Apple et à code source fermé. Pour faire didSet commencer à travailler, vous avez besoin de l'initialisation de la Liaison.
swiftPunk
0

Pour voir ce qui se passe, nous pouvons vous dévoiler le sucre syntaxique de la propriété des wrappers. @Binding var doubleValue: Double se traduit par:

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

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

Tout ce que vous faites dans didSet sera mis après la ligne _doubleValue.wrappedValue = newValue. Il devrait être évident pourquoi, lorsque vous mettez à jour doubleValue dans la couche 3, La didSet de doubleValue dans la couche 2 ou 1 n'est pas appelée. Ils sont tout simplement différentes propriétés calculées!

swiftPunk la solution passe par la création d'une nouvelle liaison dont le setter définit la structure de l' doubleValue, d'où didSet:

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

Dans d'autres langues

Cette page est dans d'autres langues

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