Burlar objects de cocoa con inicializadores no disponibles en testings unitarias

Estoy desarrollando una aplicación de iOS con Swift que utiliza el marco CoreBluetooth de Apple para comunicarse con periféricos a través de Bluetooth Low Energy. En el esfuerzo de probar un controller personalizado que implementa los protocolos CBCentralManagerDelegate y CBPeripheralDelegate , estoy proporcionando una testing doble subclass de CBCentralManager para imitar el comportamiento de la API CoreBluetooth. Las devoluciones de llamada de delegado del controller se invocan en los momentos apropiados.

Hasta ahora, esto ha estado funcionando bastante bien. Pero cuando se trata de llamar a las devoluciones de llamada de CBPeripheralDelegate , se necesita pasar un CBPeripheral . Por lo general, solo falsificaría el componente que proporciona mi propia subclass o se burlará de una instancia de CBPeripheral .

Aquí está la captura : el inicializador designado de CBPeripheral en la biblioteca Objective-C subyacente está marcado como no disponible, lo que me impide crear una instancia de CBPeripheral en mi CBCentralManager falsificado y pasarla como argumento a la CBPeripheralDelegate bajo testing. (XCode me deja con un error del comstackdor).

Hasta ahora he intentado proporcionar un inicializador personalizado en mi subclass falsa (que no funciona porque tengo que llamar al init designado no disponible con el time), anulando el inicializador con una extensión (que aparentemente no está permitida) y llamando al selector (init ) con el time de ejecución de Objective-C como si no me importa una mierda que no esté disponible. El último enfoque parece el más prometedor, pero en realidad no funciona y me deja con objects no administrados del tipo equivocado (mi class de testing).

Definitivamente he llegado a un obstáculo aquí y estaría muy contento de recibir información sobre

  1. instanciar un CBPeripheral a pesar de que init () no está disponible

  2. un enfoque diferente para la unit testing de la CBPeripheralDelegate

Me las arreglé para resolver el problema persiguiendo la idea objc-runtime y creando una Object Factory en Objective-C, que llama a la implementación del inicializador por su puntero para ignorar la marca no disponible.

Para más información, visite: http://ijoshsmith.com/2014/06/05/instantiating-classes-by-name-in-swift/ (Esto ya no funciona en Swift actual, pero puede adaptarse fácilmente)