type - swift protocol and delegate example
Swift Generics and Protocols no funcionan en UIKit (1)
Ese es el comportamiento correcto desde el punto de vista de la documentación, porque:
El método en una clase genérica no se puede representar en Objective-C
Responder al comentario de @Bell App Lab :
Abra esta página y desplácese hacia abajo a Genes ligeros . Aquí hay una nota:
Además de estas clases de colección de la Fundación, Swift ignora los genéricos ligeros Objective-C. Cualquier otro tipo que use genéricos ligeros se importa a Swift como si no estuviera parametrizado.
Básicamente, dice que los genéricos (ObjC -> Swift) se importan solo para las clases de colección Foundation y se ignora el resto, IOW importado como si no estuviera parametrizado.
Tal vez podamos esperar alguna mejora en esta área en el futuro, pero lo dudo.
TL; DR -> desplazarse hacia abajo
Al tratar de etiquetar a Apple en la Programación Orientada a Protocolo con Swift, tropecé con el siguiente problema al intentar implementar un patrón de delegación entre clases.
Comenzaré con este ejemplo:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: PhotoHandlerParent
}
Hasta aquí todo bien. Una instancia de MyViewController
sería felizmente asignada como delegado de PhotoHandler
. Pero digo que no solo quería que el objeto delegado se ajustara a PhotoHandlerParent
, sino que también fuera de la clase UIViewController
. En este ejemplo particular, para que el PhotoHandler
pueda presentar y descartar un UIImagePickerController
en nombre de su controlador de vista padre. Muy parecido:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: UIViewController, PhotoHandlerParent
}
Desafortunadamente, el código anterior no funciona en Swift. Por otro lado, Swift tiene genéricos, que pueden ayudar en este caso. Por lo tanto, uno podría intentar:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler<Parent where Parent: UIViewController, Parent: PhotoHandlerParent>: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: Parent
}
Ahora, curiosamente, una instancia de MyViewController
volvería a ser felizmente asignada como delegado de PhotoHandler
. Sin error de compilación, sin error de tiempo de ejecución. Pero...
TL; DR: el problema
Al ejecutar el código de ejemplo para esta pregunta, es posible ver que una instancia de una clase declarada con Generics y configurada como delegado de UIImagePickerController
nunca es UIImagePickerController
por ella. El UIImagePickerController
llama a una instancia de un objeto declarado sin genéricos.
Mi mejor suposición es que el compilador no se queja porque puede verificar que PhotoHandler
cumple con UIImagePickerControllerDelegate
. Sin embargo, en el tiempo de ejecución, la instancia de PhotoHandler
es en realidad una instancia de PhotoHandler<MyViewController>
, lo que de alguna manera interfiere con la UIImagePickerController
del UIImagePickerController
para identificar que su delegado realmente implementa su protocolo.
¿O me estoy perdiendo algo tal vez?
Aclamaciones