2009-05-12 11 views
17

pensé que tenía un muy buen control sobre la gestión de memoria para Objective-C, pero no puedo imaginar la siguiente situación:En el objetivo C (iphone), ¿cómo administro la memoria de las referencias '@protocol'?


@protocol MyProtocol 
@end 

@interface MyObject : NSObject { 
    id<MyProtocol> reference; 
} 
@property (nonatomic, retain) id<MyProtocol> reference; 
@end 

@implementation MyObject 
@synthesize reference; 
-(void) dealloc { 
    [reference release]; 
    [super dealloc]; 
} 
... 
@end 

Esto me da un "advertencia : '-release' no encontrado en el (los) protocolo (s) ". ¿Puedo ignorar este error de forma segura? ¿O estoy haciendo algo terriblemente malo?

Respuesta

30

Sí, puede ignorar este error de forma segura. Un objeto declarado como tipo id<MyProtocol> no puede heredar de NSObject (no tiene tiene para usar las bibliotecas Cocoa para programar en Objective-C y hay otras clases raíz incluso en Cocoa como NSProxy). Desde retain (y release, autorelease) se declaran en NSObject, el compilador no puede saber que la instancia declarada como tipo id<MyProtocol> responde a estos mensajes. Para evitar esto, Cocoa también define el protocolo NSObject que refleja la API NSObject. Si usted declara su protocolo que

@protocol MyProtocol <NSObject> 
@end 

lo que indica que MyProtocol extiende el protocolo NSObject, le fijarán.

13

Normalmente, cuando declara un objeto como id cuenta como un objeto "cualquiera" (lo que significa que Objective-C le permitirá invocar cualquier método de cualquier clase o protocolo en el id sin previo aviso).

Sin embargo, cuando declara un objeto como id<SomeProtocol>, el significado cambia. En este caso, en cambio está diciendo: solo invocaré los métodos SomeProtocol en este objeto.

El método:

- (void)release; 

se declara en el protocolo NSObject pero se han declarado explícitamente: Sólo voy a invocar MyProtocol métodos. Entonces el compilador te advierte que hayas roto tu propia promesa.

Por lo tanto, en lugar de:

id<MyProtocol> reference; 

en realidad se debe declarar:

id<MyProtocol, NSObject> reference; 

o:

NSObject<MyProtocol> reference; 

desde NSObject (la clase) implementa NSObject (el protocolo).

o:

id reference; 

que es el más amplio del lote: déjame invoca nada en este objeto y nunca se quejan.

Puede también (como se sugiere Barry Wark) tienen MyProtocol incluyen el protocolo NSObject - aunque desde una perspectiva de diseño, que normalmente sólo se hace esto, si la aplicación de MyProtocol necesariamente significa utilizar NSObject. Normalmente, sólo hacemos esto si NSObject y MyProtocol están vinculados heritarily o semánticamente.


Un poco de información acerca de la NSObject protocolo:

Todo se invoca retener/liberar/autorelease tras debe implementar este protocolo. Como se puede inferir de esto: básicamente todo lo que implementa el protocolo NSObject (a pesar de que algunas cosas no descienden de la clase NSObject base).

Otra aclaración rápida: NSObject (la clase) y NSObject (el protocolo) no son reimplementaciones de la misma API. Se dividen de la siguiente manera:

  • NSObject (protocolo) implementa todo lo necesario para manejar/inspeccionar un objeto existente en un sentido genérico (retener/liberación, IsEqual, clase, respondsToSelector: etc).

  • NSObject (clase) implementa métodos menos genéricas: construcción/destrucción, integración de hilo, la integración de secuencias de comandos.

En la mayoría de los sentidos, el protocolo es el más importante de los dos. Recuerde que la clase incluye el protocolo de modo que si se desciende desde NSObject, se obtiene tanto.

-2

Cambio

@property (nonatomic, retain) id<MyProtocol> reference; 

a

@property (nonatomic, assign) id<MyProtocol> reference; 

¿Por qué molestarse para retener el objeto que implementa el protocolo? Todo lo que necesita es un puntero al objeto mediante el cual podemos llamar a los métodos declarados en su protocolo.

+0

lo que si se pone desasignar? – user102008

+0

No se puede asumir que no necesita retener el objeto sin más contexto. – pablasso

Cuestiones relacionadas