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

222
Vistas
¿Cómo puedo diseñar un protocolo de patrón de observador genérico en Swift?

Quiero diseñar un protocolo Swift genérico para el patrón de observador para usar con diferentes tipos/clases. El problema es que parece que no puedo especificar el tipo para el método de notify() del observador.

Inicialmente, intenté crear un tipo associatedtype con mi protocolo Observer .

 protocol Observer { associatedtype T func notify(_ value: T) } protocol Observable { var observers: [Observer] { get set } func registerObserver(_ observer: Observer) func unregisterObserver(_ observer: Observer) }

Esto no funciona (error de compilación): error: protocol 'Observer' can only be used as a generic constraint because it has Self or associated type requirements .

Así que intenté usar métodos genéricos en su lugar:

 protocol Observer { func notify<T>(_ value: T) } protocol Observable { associatedtype T var observers: [Observer] { get set } // This is okay now } extension Observable { // implement registerObserver() // implement unregisterObserver() func notifyObservers<T>(_ value: T) { for observer in observers { observer.notify(value) } } }

Esto funciona bien, pero conduce a un resultado bastante interesante. Para probarlo, creé FooObserver y FooObservable :

 class FooObserver: Observer { func notify<T>(_ value: T) { print(value) } } class FooObservable: Observable { typealias T = Int // For simplicity I set T to Int type var observers: [Observer] = [] } let a = FooObserver() let b = FooObserver() var c = FooObservable() c.registerObserver(a) c.registerObserver(b) c.notifyObservers("hello") // This works, but why?

Pude notificar con éxito a mis 2 observadores de la cadena "hola". ¿Supongo que esto tiene que ver con el borrado de tipos...?

Entonces, mi pregunta es: ¿cómo puedo implementar un patrón de observador de tipo genérico en el que pueda estar seguro de que el valor en notify() es del tipo correcto?

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

0

protocol Observer { associatedtype T func notify(_ value: T) }

Esto dice que un observador dado puede manejar un tipo específico ( T ) que el observador elija.

 protocol Observable { var observers: [Observer] { get set } func registerObserver(_ observer: Observer) func unregisterObserver(_ observer: Observer) }

Esto no es válido, porque el sistema no tiene forma de saber qué T desea para estos observadores. Cada observador solo puede manejar exactamente un T .

 protocol Observer { func notify<T>(_ value: T) }

Esto es básicamente sin sentido. Dice que se puede llamar a notificar con cualquier tipo. Si eso es lo que quieres decir, quieres decir:

 protocol Observer { func notify(_ value: Any) }

Pero eso significa que cada observador tiene que lidiar con Any , lo cual no es bueno. La razón por la que funciona es que eligió print como prueba. print puede manejar Any . Cuando quiera probar este tipo de cosas, necesita probar algo como lo que realmente quiere hacer en su programa. Trabajos de imprenta para toda clase de cosas que no sirven para ningún otro fin.

El problema básico es que Observer no debería ser un protocolo. Debería ser una función. Por ejemplo:

 typealias Observer<T> = (T) -> Void protocol Observable { associatedtype T var observers: [Observer<T>] { get set } func registerObserver(_ observer: Observer<T>) func unregisterObserver(_ observer: Observer<T>) }

El problema con este enfoque es que no hay forma de implementar unregisterObserver . Tampoco tengo claro cómo implementó unregisterObserver en su código. Realmente no parece posible.

Aquí hay una manera muy simple de construir un observable:

 typealias Observer<T> = (T) -> () struct Subscription { let cancel: () -> Void } final class Observable<T> { private var observations: [UUID: Observer<T>] = [:] func subscribe(observer: @escaping Observer<T>) -> Subscription { let uuid = UUID() observations[uuid] = observer return Subscription(cancel: { [weak self] in self?.observations[uuid] = nil }) } }

(Consulte https://stackoverflow.com/a/55389143/97337 para saber de dónde proviene esto).

Para una versión más completa que es muy simple, vea Observable . Para una versión un poco más complicada que es un poco peculiar, vea Stream . Para una versión más potente y menos peculiar, consulte Propiedades . Para una versión muy potente que establece toda una forma de programación, consulte RxSwift .

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