Sobes.tech
Middle+

Šta je PreferenceKey u kontekstu SwiftUI?

sobes.tech АИ

Одговор од АИ

PreferenceKey — то је протокол у SwiftUI који омогућава пренос вредности "одоздо нагоре" кроз дрво приказа. Користи се за прикупљање информација од дечијих приказа и достављање њихових података родитељским приказима који могу користити те информације за промену свог понашања или изгледа.

Кључне карактеристике PreferenceKey:

  • Протокол: Потребно је реализовати протокол PreferenceKey, дефинишући тип вредности и метод за комбовање вредности.
  • associatedtype Value: Одређује тип података који ће се преносити.
  • static func reduce(value: inout Value, nextValue: () -> Value): Ова метода се позива од стране SwiftUI приликом сакупљања вредности од више дечијих приказа. Треба одредити како да се обједине тренутна вредност (value) и нова (nextValue()).
  • Пренос вредности: Дечији прикази користе модификатор .preference(key:value:) за постављање вредности за одређени PreferenceKey.
  • Читање вредности: Родитељски прикази користе модификатор .onPreferenceChange(_:perform:) за добијање обавештења о промени вредности за одређени PreferenceKey.

Пример:

Креирање PreferenceKey за одређивање висине дечијег приказа:

struct ChildHeightPreferenceKey: PreferenceKey {
    // Тип вредности - Опционални Double, јер дечији приказ можда још нема димензије
    typealias Value = Double?

    // Почетна вредност
    static var defaultValue: Double? = nil

    // Обједињавање вредности (у овом случају, узимамо последњу непразну вредност)
    static func reduce(value: inout Double?, nextValue: () -> Double?) {
        value = nextValue() ?? value
    }
}

Користи у приказу:

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

    var body: some View {
        VStack {
            Text("Висина дечијег приказа: \(childHeight != nil ? "\(childHeight!)" : "-")")
            ChildView()
                // Читање вредности 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) // Пример висине
                // Постављање вредности PreferenceKey
                .preference(key: ChildHeightPreferenceKey.self, value: geometry.size.height)
        }
        .frame(height: 100) // Фиксирана рамка за GeometryReader
    }
}