Middle+
Czym jest PreferenceKey w kontekście SwiftUI?
sobes.tech AI
Odpowiedź od AI
PreferenceKey to protokół w SwiftUI, który umożliwia przekazywanie wartości "z dołu do góry" w drzewie widoków. Służy do zbierania informacji od widoków potomnych i dostarczania ich widokom nadrzędnym, które mogą używać tych informacji do zmiany swojego zachowania lub wyglądu.
Kluczowe cechy PreferenceKey:
- Protokół: Należy zaimplementować protokół
PreferenceKey, definiując typ wartości i metodę łączenia wartości. associatedtype Value: Określa typ danych, które będą przekazywane.static func reduce(value: inout Value, nextValue: () -> Value): Ta metoda jest wywoływana przez SwiftUI podczas zbierania wartości od wielu widoków potomnych. Musisz zdefiniować, jak połączyć obecną wartość (value) z nową (nextValue()).- Przekazywanie wartości: Widoki potomne używają modyfikatora
.preference(key:value:)do ustawiania wartości dla konkretnegoPreferenceKey. - Odczyt wartości: Widoki nadrzędne używają modyfikatora
.onPreferenceChange(_:perform:)do otrzymywania powiadomień o zmianie wartości dla konkretnegoPreferenceKey.
Przykład:
Tworzenie PreferenceKey do określenia wysokości widoku potomnego:
struct ChildHeightPreferenceKey: PreferenceKey {
// Typ wartości - opcjonalny Double, ponieważ widok potomny może jeszcze nie mieć rozmiarów
typealias Value = Double?
// Wartość domyślna
static var defaultValue: Double? = nil
// Łączenie wartości (w tym przypadku, bierzemy ostatnią niepustą wartość)
static func reduce(value: inout Double?, nextValue: () -> Double?) {
value = nextValue() ?? value
}
}
Użycie w widoku:
struct ParentView: View {
@State private var childHeight: Double? = nil
var body: some View {
VStack {
Text("Wysokość widoku potomnego: \(childHeight != nil ? "\(childHeight!)" : "-")")
ChildView()
// Odczytanie wartości 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) // Przykład wysokości
// Ustawienie wartości PreferenceKey
.preference(key: ChildHeightPreferenceKey.self, value: geometry.size.height)
}
.frame(height: 100) // Stała ramka dla GeometryReader
}
}