Sobes.tech
Middle+

¿Qué es PreferenceKey en el contexto de SwiftUI?

sobes.tech AI

Respuesta de la IA

PreferenceKey es un protocolo en SwiftUI que permite transmitir valores "de abajo hacia arriba" a través del árbol de vistas. Se utiliza para recopilar información de vistas hijas y entregarla a las vistas padres, que pueden usar esta información para modificar su comportamiento o apariencia.

Características clave de PreferenceKey:

  • Protocolo: Es necesario implementar el protocolo PreferenceKey, definiendo el tipo de valor y el método para combinar valores.
  • associatedtype Value: Define el tipo de datos que se transmitirá.
  • static func reduce(value: inout Value, nextValue: () -> Value): Este método es llamado por SwiftUI al recopilar valores de varias vistas hijas. Debes definir cómo combinar el valor actual (value) con el nuevo (nextValue()).
  • Transmisión de valores: Las vistas hijas usan el modificador .preference(key:value:) para establecer un valor para una PreferenceKey específica.
  • Lectura de valores: Las vistas padres usan el modificador .onPreferenceChange(_:perform:) para recibir notificaciones cuando cambie el valor de una PreferenceKey específica.

Ejemplo:

Creando una PreferenceKey para determinar la altura de una vista hija:

struct ChildHeightPreferenceKey: PreferenceKey {
    // Tipo de valor - Double opcional, ya que la vista hija puede no tener tamaño aún
    typealias Value = Double?

    // Valor predeterminado
    static var defaultValue: Double? = nil

    // Combinar valores (en este caso, tomamos el último valor no nulo)
    static func reduce(value: inout Double?, nextValue: () -> Double?) {
        value = nextValue() ?? value
    }
}

Uso en la vista:

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

    var body: some View {
        VStack {
            Text("Altura de la vista hija: \(childHeight != nil ? "\(childHeight!)" : "-")")
            ChildView()
                // Leer el valor de 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) // Ejemplo de altura
                // Establecer el valor de PreferenceKey
                .preference(key: ChildHeightPreferenceKey.self, value: geometry.size.height)
        }
        .frame(height: 100) // Marco fijo para GeometryReader
    }
}