Declaraciones de Transmisión del Protocolo del Objetivo C


ObjectProperties.h

@protocol ObjectProperties <NSObject>

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSDate *date;
@property (assign, nonatomic) int64_t index;

@end

ClassA.h

#import <Foundation/Foundation.h>

@protocol ObjectProperties;

@interface ClassA : NSObject <ObjectProperties>

- (void)specialSauce;

@end;

Clase manejada.h

#import <CoreData/CoreData.h>

@protocol ObjectProperties;

@interface ManagedClassA : NSManagedObject <ObjectProperties>

- (void)doSomething;

@end;

Del ejemplo de código anterior, he definido un protocolo .archivo h para ser utilizado tanto con objetos Core Data como con objetos simples ol ' vanilla. Parece "ruido "tener clases conformes # importar el protocolo en su encabezado; sería más limpio reenviar declarar el protocolo e importar en el archivo de implementación como he mostrado arriba. Obstante, Xcode lanza una advertencia al hacerlo de esta manera:

Cannot find protocol definition for 'ObjectProperties'

El código compila, y en su mayoría funciona. Digo sobre todo porque hay algo de funkiness con los datos del núcleo tratando de crear dinámicamente los getters / setters para la propiedad escalar, pero creo que es probablemente porque he golpeado un caso de borde.

Por supuesto, el trabajo más obvio es simplemente importar el encabezado del protocolo a los encabezados de la clase.

Si mi entendimiento es correcto (y mi conocimiento es muy reciente si importo el protocolo en las cabeceras de mi clase y hago un cambio en el protocolo, entonces todos los archivos subsecuentes que importen mis clases tendrán que ser recompilados.

¿Cuál es la forma correcta de resolver este tipo de problema?

Author: edelaney05, 2012-07-18

4 answers

No se puede reenviar una superclase o un protocolo al que se ajusta. En esos casos, debe incluir el encabezado. Esto se debe a que (en el caso de la superclase) las variables de instancia y los métodos de la superclase se convierten en parte de su clase; o (en el caso de los protocolos) los métodos del protocolo se convierten en métodos declarados en su clase, sin necesidad de declararlos explícitamente. (es decir, Ahora otras personas que incluyen el encabezado de su clase verán que su clase declara esos métodos, como si las declaró usted mismo.) La única manera de que eso sea posible es si ya estuvieran definidos en este ámbito, es decir, si sus encabezados son importados.

#import <SomeClass.h>
#import <SomeProtocol.h> // these two must be imported

@interface MyClass : SomeClass <SomeProtocol>
@end

Las declaraciones forward son útiles para cosas que solo se muestran en el tipo de una variable (específicamente, una variable de puntero de objeto). Los punteros de objeto son todos del mismo tamaño y no hay diferencia entre diferentes tipos de punteros de objeto en tiempo de ejecución (el concepto de tipo de puntero de objeto es solo una cosa en tiempo de compilación). Así que no hay necesidad real de saber exactamente lo que hay en las clases de esos tipos. Por lo tanto, se pueden declarar hacia adelante.

@class SomeClass;
@protocol SomeProtocol; // you can forward-declare these

@interface MyClass {
    SomeClass *var1;
    id<SomeProtocol> var2;
}
@end
 101
Author: newacct,
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
2012-07-18 03:17:00

Sí, tiene razón en que todos los archivos tendrán que ser recompilados, pero esto es necesario. Los archivos que importan el encabezado de la clase deben conocer los métodos asociados con el protocolo que implementa. Si guardas esa definición en el .m archivo entonces solo es visible a un archivo (desde .m los archivos nunca se importan). No es lo mismo que declarar clases. Si reenvía declarar un protocolo, debe declararlo en algún lugar que sea visible en el mismo ámbito que el reenvío declaración. No puedo pensar en ningún ejemplo donde esto no ocurra en el mismo archivo.

En ARC esto es un error, porque ARC necesita saber acerca de la gestión de memoria de los métodos declarados (¿devuelven instancias +1, punteros internos, etc.?)

 4
Author: borrrden,
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
2012-07-18 01:57:57

Declarando su clase en MyClass.h, usted tiene que importar todos los archivos de cabecera para su superclase, así como los protocolos que adoptó en el MyClass.archivo h. Protocolos en Objective-c se considera como un tipo variante de herencia.

Las declaraciones forward se suelen utilizar en la declaración de los miembros de la clase .

 2
Author: xingzhi.sg,
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
2012-07-18 02:11:02

Ya que está declarando conformidad con el protocolo, debe #importar el encabezado que contiene el protocolo.

Esto es lo mismo que #importar una superclase, en lugar de declararla hacia adelante:

@class Foo;

@interface Bar : Foo
// Will get error: attempting to use the forward class 'Foo' as superclass of 'Bar'
@end;
 1
Author: Steven Fisher,
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
2012-07-18 02:15:06