Назад к вопросам
Middle+
77
questionbank

Что такое PreferenceKey в контексте разработки на iOS?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

PreferenceKey — это протокол в SwiftUI, позволяющий передавать значения из дочерних представлений вверх по иерархии представлений. Используется для сбора информации о размерах, положении или других характеристиках дочерних представлений, которую можно использовать в родительских представлениях для принятия решений о компоновке или поведении.

Основные компоненты:

  1. Ключ (Key): Тип, реализующий протокол PreferenceKey. Определяет тип значения, которое будет передаваться, и способ объединения нескольких значений (reduce метод).
    struct MySizePreferenceKey: PreferenceKey {
        static var defaultValue: CGSize = .zero // Начальное значение
    
        static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
            // Логика объединения значений.
            // В данном случае, можно выбрать максимальный размер или суммировать.
            // Пример: value = max(value, nextValue())
            // Пример для суммирования: value.width += nextValue().width; value.height += nextValue().height
             value = nextValue() // Просто берем последнее значение (для примера)
        }
    }
    
  2. Установка значения: Дочернее представление устанавливает значение с помощью модификатора .preference(key:value:).
    Text("Привет")
        .background(GeometryReader { geometry in
            Color.clear.preference(key: MySizePreferenceKey.self, value: geometry.size)
        })
    
  3. Чтение значения: Родительское представление читает собранное значение с помощью модификатора .onPreferenceChange.
    VStack {
        // Дочерние представления, устанавливающие предпочтения
        Text("Пример 1")
            .background(GeometryReader { geometry in
                Color.clear.preference(key: MySizePreferenceKey.self, value: geometry.size)
            })
    
        Text("Пример 2 длинный")
            .background(GeometryReader { geometry in
                Color.clear.preference(key: MySizePreferenceKey.self, value: geometry.size)
            })
    }
    .onPreferenceChange(MySizePreferenceKey.self) { size in
        // Здесь можно использовать агрегированный размер
        print("Агрегированный размер:", size)
    }
    

Когда использовать:

  • Получение размеров дочерних элементов для адаптивной компоновки родителя.
  • Передача информации о расположении элементов.
  • Создание пользовательских якорей (anchors).
  • Сбор состояния или свойств из нескольких дочерних представлений.

Отличие от Environment:

  • Environment передает данные вниз по иерархии представлений.
  • PreferenceKey передает данные вверх по иерархии представлений и позволяет собирать/объединять значения из нескольких дочерних элементов.