registrarse para libros leer gratis español ebook descargar bajar objective-c compiler-construction memory-management properties

objective c - libros - ¿Cómo se maneja la liberación para las propiedades de retención @synthesized?



ebook gratis (4)

Tengo algunas preguntas sobre las propiedades sintetizadas en Objective-C. La lista completa sigue, pero la pregunta básica es esta: ¿cómo garantiza el compilador que los ivars para las propiedades sintetizadas se lanzan correctamente, aunque mi código puede incluir o no métodos de publicación en dealloc?

Nota: Decidí no publicar estas preguntas como individuales porque están muy relacionadas y porque hay un puñado de preguntas existentes que abordan los problemas individuales sin llegar realmente al meollo del asunto.

Preguntas algo similares:

Configuración: considere una clase con una sola propiedad:

@interface Person : NSObject { NSString * name; } @property (nonatomic, retain) name; @end

Pregunta # 1: El caso muy básico:

@implementation Person @synthesize name; @end

Con esta configuración, asumo que el name lanzará automáticamente cada vez que se suelte un objeto Person . En mi opinión, el compilador simplemente inserta [name release] en el método dealloc como si yo mismo lo hubiera escrito. ¿Es eso correcto?

Pregunta # 2: Si elijo escribir mi propio método dealloc para esta clase, y omito una llamada a [name release] , ¿se filtrará?

@implementation Person @synthesize name; - (void)dealloc { [super dealloc]; } @end

Pregunta n. ° 3: si elijo escribir mi propio método dealloc para esta clase, e dealloc una llamada a [name release] , ¿dará como resultado una versión doble, ya que @synthesize ya se ha ocupado de mí?

@implementation Person @synthesize name; - (void)dealloc { [name release]; [super dealloc]; } @end

Pregunta # 4: Si elijo escribir mi propio acceso a la propiedad para esta clase, pero no escribo mi propio método dealloc , ¿se dealloc name ?

@implementation Person @dynamic name; - (void)setName:(NSString *)newName { [newName retain]; [name release]; name = newName; } @end

Pregunta n. ° 5: tengo la sensación (basada en la experiencia) de que ninguno de los escenarios anteriores dará como resultado filtraciones o dobles lanzamientos, ya que el lenguaje ha sido diseñado para evitarlos. Eso, por supuesto, plantea la pregunta de "¿cómo?". ¿Es el compilador simplemente lo suficientemente inteligente como para realizar un seguimiento de todos los casos posibles? ¿Qué pasaría si tuviera que hacer lo siguiente? (Tenga en cuenta que este es un ejemplo ridículo, solo para ilustrar mi punto):

void Cleanup(id object) { [object release]; } @implementation Person @synthesize name; - (void)dealloc { Cleanup(name); } @end

¿ dealloc al compilador para que agregue otro [name release] al método dealloc ?


De la documentación de Objective-C en propiedades :

dealloc

Las propiedades declaradas toman fundamentalmente el lugar de las declaraciones de métodos de acceso; cuando sintetiza una propiedad, el compilador solo crea los métodos de acceso ausentes. No hay interacción directa con el método dealloc: las propiedades no se liberan automáticamente. Las propiedades declaradas, sin embargo, proporcionan una forma útil de verificar la implementación de su método dealloc: puede buscar todas las declaraciones de propiedad en su archivo de encabezado y asegurarse de que las propiedades del objeto que no están marcadas assign se liberen, y las que se marcan asignar son no publicado.

Esto esencialmente responde todas tus preguntas.


Hay algo más que vale la pena saber: si tiene una propiedad sintetizada, establecer esa propiedad en cero (usando la sintaxis de punto, por supuesto) liberará el ivar por usted.


La regla simple y general: si asigna, retiene o copia un objeto, USTED tiene que liberarlo.

Cuando utiliza la configuración semántica del colocador de retain en una instrucción @synthesize , le está pidiendo al compilador que @synthesize para usted un configurador que llama retain en el objeto. Nada más y nada menos. Y como está reteniendo ese objeto (aunque sea a través de un código autogenerado mágicamente), tiene que liberarlo, y dónde liberarlo está en -(void)dealloc .


Q1:

No. @synthesize no modifica el -dealloc por ti. Tienes que- -release el name tú mismo.

Q2:

Sí, se filtrará. La misma razón que Q1.

Q3:

No, no será de doble lanzamiento. La misma razón que Q1.

Q4:

Sí, se filtrará. La misma razón que Q1.

Q5:

No, no será de doble lanzamiento. La misma razón que Q1.

Puede verificar esto usted mismo -retain -dealloc y -dealloc y -dealloc para informar lo que está sucediendo.

#import <Foundation/Foundation.h> @interface X : NSObject {} @end @implementation X -(oneway void)release { NSLog(@"Releasing %p, next count = %d", self, [self retainCount]-1); [super release]; } -(id)retain { NSLog(@"Retaining %p, next count = %d", self, [self retainCount]+1); return [super retain]; } -(void)dealloc { NSLog(@"Dealloc %p", self); [super dealloc]; } @end @interface Y : NSObject { X* x; } @property (nonatomic, retain) X* x; @end @implementation Y @synthesize x; - (void)dealloc { [x release]; [super dealloc]; } @end int main () { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; Y* y = [[Y alloc] init]; X* x = [[X alloc] init]; y.x = x; [y release]; [x release]; [pool drain]; return 0; }

En Q1, Q2 y Q4, el último -retainCount de -retainCount de x es 1, por lo que hay una fuga, y en Q3 y Q5, el último -retainCount es 0 y se llama -dealloc , por lo que no hay pérdida.