¿Puede una categoría implementar simultáneamente un protocolo?


Si una categoría que estoy creando para una clase agrega métodos que también cumplen con el contrato establecido por un protocolo, me gustaría marcar esa clase de categoría como implementando el protocolo, y por lo tanto indicar al preprocesador Obj-C que la clase implementa efectivamente el protocolo también.

Ejemplo delegado (para mayor claridad, gracias Ole!):

@protocol SomeDelegate <NSObject>
  - (void)someDelegateMessage;
@end

Categoría de ejemplo:

@interface NSObject (SomeCategory) <SomeDelegate>
  - (void)someDelegateMessage;    
@end

Y con una implementación típica

@implement NSObject (SomeCategory)
  - (void)someDelegateMessage {}
@end

Cuando realmente intento esto, obtengo un advertencia para cada método NSObject:

Advertencia: implementación incompleta de la categoría "SomeCategory"

Advertencia: no se encuentra la definición del método para '-description'

...

Advertencia: definición del método para' - isEqual: 'no encontrado

Advertencia: la categoría 'SomeCategory' no implementa completamente el protocolo 'NSObject'

Funciona bien si elimino <SomeDelegate> de la declaración, pero por supuesto NSObject no se reconoce como un SomeDelegate

Author: smorgan, 2009-11-01

3 answers

Una solución es declarar el protocolo en una categoría sin implementación, e implementar el método en una categoría diferente, por ejemplo:

@interface NSObject (SomeCategory) <SomeDelegate>
  - (void)someDelegateMessage;    
@end

@implementation NSObject (SomeCategory_Impl)
  - (void)someDelegateMessage {}
@end

Si hace esto, NSObject se considerará que se ajusta a <SomeDelegate> en tiempo de compilación, y las comprobaciones en tiempo de ejecución de someDelegateMessage tendrán éxito. Sin embargo, conformsToProtocol: las comprobaciones en tiempo de ejecución fallarán.

Por supuesto, debe presentar un error solicitando que los métodos declarados en la clase core no generen advertencias.

 13
Author: Jens Ayton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-20 18:46:27

¿Hay alguna posibilidad de que su declaración de protocolo incluya el protocolo NSObject? Así:

@protocol SomeDelegate <NSObject>
...

De ahí vienen las advertencias porque ahora tu categoría no implementa el protocolo completo. En el código de prueba que acabo de escribir, eliminar NSObject del protocolo elimina las advertencias del compilador.

 5
Author: Ole Begemann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-01 00:17:50

Si desea que el compilador se calle sobre el envío de mensajes (y es importante que recuerde que ese es el nombre del protocolo, no el nombre de la clase), entonces solo use variables 'id', no 'id' ya que eso le dice explícitamente al compilador "Este es un objeto que solo implementa el protocolo SomeDelegate".

Alternativamente, use NSObject como su tipo de variable.

 1
Author: Jeff Laing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-01 09:06:59