Sobes.tech
Middle+

Какво е PreferenceKey в контекста на SwiftUI?

sobes.tech AI

Отговор от AI

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 {
    // Типът на стойността - Optional 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
    }
}