2012-07-18 6 views
51

ObjectProperties.hde Objective-C Protocolo Delantero Declaraciones

@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; 

ManagedClassA.h

#import <CoreData/CoreData.h> 

@protocol ObjectProperties; 

@interface ManagedClassA : NSManagedObject <ObjectProperties> 

- (void)doSomething; 

@end; 

Desde el ejemplo de código anterior, he definido un protocolo en un archivo .h para ser utilizado tanto con objetos de Datos de Núcleo como con simples objetos de vanilla. Parece que "ruido" tiene clases conformes # importa el protocolo en el encabezado; Sería más limpio reenviar declarar el protocolo & importar en el archivo de implementación como he mostrado anteriormente. Sin embargo, Xcode lanza una advertencia cuando se hace de esta manera:

Cannot find protocol definition for 'ObjectProperties'

El código se compila, y sobre todo funciona. Digo sobre todo porque hay algo de funkiness con Core Data tratando de crear dinámicamente los getters/setters para la propiedad escalar, pero creo que es probablemente porque he tocado un caso extremo.

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

Si mi comprensión es correcta (y mi conocimiento es adquirido muy recientemente, por lo que es completamente posible que esté equivocado), si importo el protocolo en mis encabezados de clase y realizo un cambio en el protocolo, todos los posteriores los archivos que importan mis clases deberán ser recompilados.

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

+0

Tengo un problema similar pero con un protocolo Swift. – Alper

Respuesta

93

no se puede declarar una superclase hacia adelante o un protocolo que se ajusta a. En esos casos, debe incluir el encabezado.Esto se debe a que (en el caso de la superclase) las variables y métodos de instancia de la superclase se vuelven 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 incluyan el encabezado de su clase verán que su clase declara esos métodos, como si los hubiera declarado usted mismo). La única forma de que eso sea posible es si ya se definieron en este ámbito, es decir, se importaron sus encabezados. .

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

@interface MyClass : SomeClass <SomeProtocol> 
@end 

declaraciones adelantadas son útiles para las cosas que acaba de aparecer en el tipo de una variable (en concreto, una variable de puntero de objeto). Los punteros a objetos son todos del mismo tamaño y no hay diferencia entre los diferentes tipos de punteros a objetos en tiempo de ejecución (el concepto de tipo de puntero a objeto es solo una cosa de tiempo de compilación). Entonces no hay una necesidad real de saber exactamente qué hay en las clases de esos tipos. Por lo tanto, pueden ser declarados adelante.

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

@interface MyClass { 
    SomeClass *var1; 
    id<SomeProtocol> var2; 
} 
@end 
4

Sí, tiene la razón de que todos los archivos deberán ser recompilados, pero esto es necesario. Los archivos que importan el encabezado de clase necesitan conocer los métodos asociados con el protocolo que implementa. Si oculta esa definición en el archivo .m, solo estará visible para un archivo (ya que los archivos .m nunca se importarán). No es lo mismo que las clases que declaran hacia adelante. Si reenvía declara un protocolo, debe declararlo en algún lugar que sea visible en el mismo ámbito que la declaración directa. 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 (¿Vuelven +1 casos, punteros internos, etc?)

2

Al declarar su clase en MyClass.h , debe importar todos los archivos de encabezado para su superclase, así como los protocolos que adoptó en el archivo MyClass.h. Los protocolos en Objective-c se consideran como un tipo de herencia variante.

Las declaraciones directas se usan generalmente en la declaración de miembro de la clase.

1

Dado que declara conformidad con el protocolo, debe importar el encabezado que contiene el protocolo.

Esto es lo mismo que #importing una superclase, en lugar de hacia adelante declarando que:

@class Foo; 

@interface Bar : Foo 
// Will get error: attempting to use the forward class 'Foo' as superclass of 'Bar' 
@end; 
Cuestiones relacionadas