Sobes.tech
Middle+

Cos'è PreferenceKey nel contesto di SwiftUI?

sobes.tech AI

Risposta dell'AI

PreferenceKey è un protocollo in SwiftUI che consente di trasmettere valori "dal basso verso l'alto" attraverso l'albero delle visualizzazioni. Viene utilizzato per raccogliere informazioni dalle visualizzazioni figlie e consegnarle alle visualizzazioni genitore, che possono usare queste informazioni per modificare il proprio comportamento o aspetto.

Caratteristiche principali di PreferenceKey:

  • Protocolo: È necessario implementare il protocollo PreferenceKey, definendo il tipo di valore e il metodo per combinarli.
  • associatedtype Value: Definisce il tipo di dati che verrà trasmesso.
  • static func reduce(value: inout Value, nextValue: () -> Value): Questo metodo viene chiamato da SwiftUI durante la raccolta dei valori da più visualizzazioni figlie. Devi definire come combinare il valore corrente (value) con il nuovo (nextValue()).
  • Trasmissione dei valori: Le visualizzazioni figlie usano il modificatore .preference(key:value:) per impostare un valore per una PreferenceKey specifica.
  • Lettura dei valori: Le visualizzazioni genitore usano il modificatore .onPreferenceChange(_:perform:) per ricevere notifiche quando il valore di una PreferenceKey cambia.

Esempio:

Creazione di una PreferenceKey per determinare l'altezza di una visualizzazione figlia:

struct ChildHeightPreferenceKey: PreferenceKey {
    // Tipo di valore - Double opzionale, poiché la visualizzazione figlia potrebbe non avere ancora dimensioni
    typealias Value = Double?

    // Valore di default
    static var defaultValue: Double? = nil

    // Unione dei valori (in questo caso, prendi l'ultimo valore non nullo)
    static func reduce(value: inout Double?, nextValue: () -> Double?) {
        value = nextValue() ?? value
    }
}

Utilizzo nella visualizzazione:

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

    var body: some View {
        VStack {
            Text("Altezza della visualizzazione figlia: \(childHeight != nil ? "\(childHeight!)" : "-")")
            ChildView()
                // Lettura del valore di 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) // Esempio di altezza
                // Impostazione del valore di PreferenceKey
                .preference(key: ChildHeightPreferenceKey.self, value: geometry.size.height)
        }
        .frame(height: 100) // Cornice fissa per GeometryReader
    }
}