Sobes.tech
Middle+

Co je PreferenceKey v kontextu SwiftUI?

sobes.tech AI

Odpověď od AI

PreferenceKey je protokol ve SwiftUI, který umožňuje přenos hodnot "zdola nahoru" přes strom pohledů. Používá se ke sběru informací od podřízených pohledů a jejich doručení rodičovským, které tyto informace mohou využít ke změně svého chování nebo vzhledu.

Klíčové vlastnosti PreferenceKey:

  • Protokol: Je nutné implementovat protokol PreferenceKey, který definuje typ hodnoty a metodu pro jejich slučování.
  • associatedtype Value: Určuje typ dat, která budou přenášena.
  • static func reduce(value: inout Value, nextValue: () -> Value): Tato metoda je volána SwiftUI při sběru hodnot od více podřízených pohledů. Musíte definovat, jak sloučit aktuální hodnotu (value) s novou (nextValue()).
  • Přenášení hodnot: Podřízené pohledy používají modifikátor .preference(key:value:) k nastavení hodnoty pro konkrétní PreferenceKey.
  • Čtení hodnot: Rodičovské pohledy používají modifikátor .onPreferenceChange(_:perform:) k získání oznámení o změně hodnoty pro konkrétní PreferenceKey.

Příklad:

Vytvoření PreferenceKey pro určení výšky podřízeného pohledu:

struct ChildHeightPreferenceKey: PreferenceKey {
    // Typ hodnoty - volitelný Double, protože podřízený pohled ještě nemusí mít rozměry
    typealias Value = Double?

    // Výchozí hodnota
    static var defaultValue: Double? = nil

    // Sloučení hodnot (v tomto případě, vezmeme poslední nenulovou hodnotu)
    static func reduce(value: inout Double?, nextValue: () -> Double?) {
        value = nextValue() ?? value
    }
}

Použití v pohledu:

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

    var body: some View {
        VStack {
            Text("Výška podřízeného pohledu: \(childHeight != nil ? "\(childHeight!)" : "-")")
            ChildView()
                // Čtení hodnoty 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) // Příklad výšky
                // Nastavení hodnoty PreferenceKey
                .preference(key: ChildHeightPreferenceKey.self, value: geometry.size.height)
        }
        .frame(height: 100) // Pevný rám pro GeometryReader
    }
}