Pregunta

Estoy pasando por toda mi documentación con respecto a la gestión de la memoria y estoy un poco confundido sobre algo.

Cuando usas @Property, crea getters/setters para el objeto:

.h: @property (retener, no atómico) nsstring *mystring

.m: @synthesize mystring

Entiendo eso, pero donde me confunde es el uso de uno mismo. Veo diferentes sintaxis en diferentes blogs y libros. He visto:

myString = [NSString alloc] initWithString:@"Hi there"];

o

self.myString = [NSString alloc] initWithString:@"Hi there"];

Luego, en DealLoc, veo:

self.myString = nil;

o

[myString release];

o

self.myString = nil;
[myString release];

En este sitio, ¿alguien declaró que usar yo agrega otro incremento al recuento de retención? Es cierto, no he visto eso en ningún lado.

¿Los getters/setters automáticos que se proporcionan con autorrealización?

¿Cuál es la forma correcta de hacer todo esto?

¡Gracias!

¿Fue útil?

Solución

Si no está utilizando la sintaxis del punto, no está utilizando ningún setter o getter.

Lo siguiente es que depende de cómo se haya declarado la propiedad.

Supongamos que algo como esto:

@property (nonatomic, retain) Article *article;
...
@synthesize article;

Asignación algo para artículo con

self.article = [[Article alloc] init];

superará la instancia dada por Alloc/init y causará una fuga. Esto se debe a que el setter del artículo lo retendrá y lanzará cualquier instancia anterior para usted.

Para que puedas reescribirlo como:

self.article = [[[Article alloc] init] autorelease];

Haciendo esto

article = [[Article alloc] init]; 

También está bien, pero podría implicar una fuga, ya que el artículo puede tener una referencia a una instancia ya. Por lo tanto, se necesitaría liberar el valor de antemano:

[article release];
article = [[Article alloc] init]; 

Librar memoria podría hacerse con

[article release];

o con

self.article = nil;

El primero accede al campo directamente, no se involucran a Setters/Getters. El segundo se establece en el campo usando un setter. Que lanzará la instancia actual, si hay una antes de configurarla en nulo.

Esta construcción

self.myString = nil; 
[myString release];

es demasiado, en realidad envía la liberación a nulo, lo cual es inofensivo pero también innecesario.

Solo tiene que mapear mentalmente HAT usando la sintaxis del punto es usar métodos de accesorios:

self.article = newArticle
// is
[self setArticle:newArticle];

y

myArticle = self.article;
// is
myArticle = [self article];

Algunas sugerencias sobre lectura, todos los documentos oficiales de Apple:

El lenguaje de programación Objective-C

Guía de programación de gestión de memoria

Otros consejos

Cuando creas un retain Setter, estás creando algo como esto:

- (void)setString:(NSString *)someString {
    if (someString != string) {
        [string release];
        [someString retain];
        string = someString;
    }
}

Si no usa el setter, el nuevo valor no está obteniendo eso, no "posee" esa cadena, y debido a que son todas las referencias, si se lanza la cadena original, puede estar enfrentando una referencia nula, que conducirá a un EXC_BAD_ACCESS. El uso del setter garantiza que su clase ahora tenga una copia de ese valor, así que sí, incrementa el recuento de retención del nuevo valor. (Tenga en cuenta que usar el Getter es una convención de OOP: que los extraños no deberían poder tocar directamente el IVAR. También en su Getter puede modificar el valor, tal vez devolver un NsArray cuando su IVAR es un NsmutableArray, por ejemplo).

No deberías autorelease En un setter, el Apple lo ha usado en su código de muestra, pero algo a tener en cuenta es que los establecedores se llaman mucho, miles de millones de veces, potencialmente. Todos esos objetos están entrando en la misma piscina de autorazones, por lo que a menos que cree el suyo y/o enjuague regularmente, tendrá un montón de elementos en su piscina, todos innecesarios pero aún tomando Ram. Mucho mejor para simplemente release.

En cuanto a DealLoc, rastree a través de ese setter. Si envía un release Directamente, es obvio: liberas ese objeto. Pero si escribes self.string = nil;, lo que estás haciendo es esto:

  1. El valor nulo no es el mismo, por lo que ingresa al if bloquear
  2. Liberas el valor anterior, lo que quieres hacer
  3. retain nulo: los mensajes para no hacer nada, y no se bloquea
  4. Establece nulo, que no ocupa ningún recuerdo, a la cadena, que ahora está efectivamente vacía

Como cuestión de convención, uso release en mi dealloc método, porque release parece más final y dealloc es el método final llamar que recibirá su objeto. yo suelo self.string = nil; en ViewDidUnload y los métodos de advertencia de memoria.

¡Espero que esto ayude!

Además de la respuesta de Nick: los getters/setters sintetizados no proporcionan autoreloz (por cierto, ¿cuál es la gran idea de hacer esto? Bueno, puedes usar Getter como una fábrica, pero no es una forma común en el objetivo C).

Luego, en DealLoc, veo:

self.mystring = nil;

o

Liberación de MyString];

o

self.mystring = nil; [Liberación de MyString];

En DealLoc realmente no importa qué forma de liberación esté utilizando. Pero la buena manera es nulo de sus campos al liberarlos :) Prefiero usar self.myString = nil; en DealLoc

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top