Sobes.tech
Middle+

Qu'est-ce que PreferenceKey dans le contexte de SwiftUI?

sobes.tech IA

Réponse de l'IA

PreferenceKey est un protocole dans SwiftUI qui permet de transmettre des valeurs "de bas en haut" à travers l'arbre de vues. Il est utilisé pour collecter des informations à partir de vues enfants et les transmettre aux vues parentales, qui peuvent utiliser ces informations pour modifier leur comportement ou leur apparence.

Caractéristiques clés de PreferenceKey:

  • Protocole: Il faut implémenter le protocole PreferenceKey, en définissant le type de valeur et la méthode pour combiner les valeurs.
  • associatedtype Value: Définit le type de données qui sera transmis.
  • static func reduce(value: inout Value, nextValue: () -> Value): Cette méthode est appelée par SwiftUI lors de la collecte des valeurs de plusieurs vues enfants. Vous devez définir comment fusionner la valeur actuelle (value) avec la nouvelle (nextValue()).
  • Transmission de valeurs: Les vues enfants utilisent le modificateur .preference(key:value:) pour définir une valeur pour une PreferenceKey spécifique.
  • Lecture des valeurs: Les vues parentales utilisent le modificateur .onPreferenceChange(_:perform:) pour recevoir des notifications lorsque la valeur d'une PreferenceKey spécifique change.

Exemple:

Création d'une PreferenceKey pour déterminer la hauteur d'une vue enfant:

struct ChildHeightPreferenceKey: PreferenceKey {
    // Type de valeur - Double optionnel, car la vue enfant peut ne pas avoir encore de taille
    typealias Value = Double?

    // Valeur par défaut
    static var defaultValue: Double? = nil

    // Fusionner les valeurs (dans ce cas, prendre la dernière valeur non nulle)
    static func reduce(value: inout Double?, nextValue: () -> Double?) {
        value = nextValue() ?? value
    }
}

Utilisation dans la vue:

struct ParentView: View {
    @State private var childHeight: Double? = nil

    var body: some View {
        VStack {
            Text("Hauteur de la vue enfant : \(childHeight != nil ? "\(childHeight!)" : "-")")
            ChildView()
                // Lire la valeur de PreferenceKey
                .onPreferenceChange(ChildHeightPreferenceKey.self) { newValue in
                    self.childHeight = newValue
                }
        }
    }
}

struct ChildView: View {
    var body: some View {
        GeometryReader { geometry in
            Rectangle()
                .fill(Color.blue)
                .frame(height: 100) // Exemple de hauteur
                // Définir la valeur de PreferenceKey
                .preference(key: ChildHeightPreferenceKey.self, value: geometry.size.height)
        }
        .frame(height: 100) // Cadre fixe pour GeometryReader
    }
}