Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

166
Vistas
Observar una lista de Swift KeyPaths

Tengo el siguiente código que agrega un observador en dos propiedades:

 obs = [] let xa = self.observe(\CirclePolygon.radius, options: [.new]) { (op, ch) in callback() } obs.append(xa) let xb = self.observe(\CirclePolygon.origin.x, options: [.new]) { (op, ch) in callback() } obs.append(xb)

Funciona, pero no me gusta la duplicación. He intentado pasar una lista de KeyPaths:

 obs = [] let keyPaths = [\CirclePolygon.radius, \CirclePolygon.origin.x] for keyPath in keyPaths { let xa = self.observe(keyPath, options: [.new]) { (op, ch) in callback() } obs.append(xa) }

Pero aparece el error del compilador: Generic parameter 'Value' could not be inferred

¿Hay alguna forma de hacer esto?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

En primer lugar, recuerde que KVO solo funciona en instancias de NSObject (o una subclase). Entonces, si la propiedad de origin de CirclePolygon es un CGPoint o alguna otra struct , obtendrá un error de tiempo de ejecución cuando intente registrar un observador de \CirclePolygon.origin.x , porque KVO no puede aplicarse a la propiedad x de un CGPoint .

En segundo lugar, las rutas clave que proporcionó tienen diferentes tipos. Digamos (para abordar mi primer punto) que desea observar el radius (un Double ) y el origin (un CGPoint ). Las rutas clave tienen diferentes tipos:

 \CirclePolygon.radius // type: KeyPath<CirclePolygon, Double> \CirclePolygon.origin // type: KeyPath<CirclePolygon, CGPoint>

Si intenta colocarlos en una sola matriz, sin especificar explícitamente el tipo de matriz, Swift lo deducirá de la siguiente manera:

 let keyPaths = [\CirclePolygon.origin, \CirclePolygon.radius] // deduced type of keyPaths: [PartialKeyPath<CirclePolygon>]

Deduce [PartialKeyPath<CirclePolygon>] porque PartialKeyPath<CirclePolygon> es el ancestro común más cercano de KeyPath<CirclePolygon, Double> y KeyPath<CirclePolygon, CGPoint> .

Por lo tanto, en el ciclo for en el que itera sobre la matriz, está pasando un objeto con tipo estático PartialKeyPath<CirclePolygon> como el argumento keyPath del método observe(_:options:changeHandler:) . Desafortunadamente, ese método se declara de la siguiente manera :

 public func observe<Value>( _ keyPath: KeyPath<Self, Value>, options: NSKeyValueObservingOptions = [], changeHandler: @escaping (Self, NSKeyValueObservedChange<Value>) -> Void) -> NSKeyValueObservation

Es decir, el método requiere un KeyPath<Self, Value> pero está pasando un PartialKeyPath<Self> , por lo que Swift emite un error. Como suele ocurrir con los errores de Swift relacionados con problemas de tipo genérico, el error no es muy útil.

No puede resolver este problema con la conversión, porque no puede (por ejemplo) convertir KeyPath<CirclePolygon, Double> a KeyPath<CirclePolygon, Any> .

Una solución puede ser usar una función local para encapsular el código común, como esta:

 func register(callback: @escaping () -> ()) -> [NSKeyValueObservation] { func r<Value>(_ keyPath: KeyPath<CirclePolygon, Value>) -> NSKeyValueObservation { return observe(keyPath, options: []) { (_, _) in callback() } } return [ r(\.radius), r(\.origin), ] }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda