Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

164
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!