La propiedad Objective C NSString * conserva el recuento de rarezas

Tengo la siguiente clase de ejemplo:

Test.h:

@interface Test : UIButton { NSString *value; } - (id)initWithValue:(NSString *)newValue; @property(copy) NSString *value; 

Test.m:

 @implementation Test @synthesize value; - (id)initWithValue:(NSString *)newValue { [super init]; NSLog(@"before nil value has retain count of %d", [value retainCount]); value = nil; NSLog(@"on nil value has retain count of %d", [value retainCount]); value = newValue; NSLog(@"after init value has retain count of %d", [value retainCount]); return self; } 

Que produce el siguiente resultado:

 2008-12-31 09:31:41.755 Concentration[18604:20b] before nil value has retain count of 0 2008-12-31 09:31:41.756 Concentration[18604:20b] on nil value has retain count of 0 2008-12-31 09:31:41.757 Concentration[18604:20b] after init value has retain count of 2147483647 

Lo estoy llamando así:

 Test *test = [[Test alloc] initWithValue:@"some text"]; 

¿No debería el valor tener un conteo retenido de 1? ¿Qué me estoy perdiendo?

Gracias por tu ayuda.

No mires los conteos de retención. No son útiles y solo te inducirán a error: no puedes estar seguro de que nada más está reteniendo un objeto, que un objeto que obtienes de algún lado no se comparte.

En cambio, concéntrese en la propiedad del objeto y siga al pie de la letra las reglas de administración de la memoria del cocoa . De esa forma, la administración de su memoria será correcta sin importar las optimizaciones que Cocoa pueda estar haciendo detrás de las escenas por usted. (Por ejemplo, implementar -copy como simplemente -retain para objetos inmutables).

Además, es fundamental comprender la diferencia entre las propiedades de los objetos y las variables de instancia dentro de los objetos. En el código de su pregunta, está asignando un valor a una variable de instancia. Esa variable de instancia es solo eso: una variable. Asignarlo se comportará como cualquier otra asignación de variable. Para usar la propiedad, debe usar la syntax de punto o la syntax de paréntesis para invocar realmente el método de establecimiento de la propiedad:

 self.value = newValue; // this is exactly equivalent to the next line [self setValue:newValue]; // this is exactly equivalent to the previous line 

El código generado para la syntax de punto y la syntax de paréntesis es idéntico, y ninguno accederá directamente a la variable de instancia.

Estás pasando una cadena literal. El comstackdor probablemente lo asigna a la memoria estática y establece el recuento de retenciones al máximo valor posible.

Pruebe una cadena asignada dinámicamente y vea qué sucede.

 NSString* string = [[NSString alloc] initWithString: @"some text"]; Test* test = [[Test alloc] initWithValue: string]; 

Estás pasando una constante de cadena, que en realidad no puede desasignarse. Creo que 2147483647 es probablemente UINT_MAX, lo que básicamente significa que el objeto no puede ser liberado.

Creo que quieres hacer esto:

 self.value = newValue; 

que invocará al establecedor de propiedades y hará que la copia ocurra. “value = newValue” simplemente asigna un valor de puntero a la variable de instancia.

Tienes una referencia a una cadena inmutable. La asignación no necesita copiar el valor (los datos de cadena) ya que es inmutable. Si realiza una operación mutable, como value = [newValue uppercaseString], debe copiar los bits en valor y el conteo de retención del valor incrementado.

No debe prestar atención a los recuentos de retención, solo siga las reglas de administración de la memoria Cocoa. http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

hmm … nos estamos acercando.

parece que el conteo de retención de newValue también es 2147483647.

Traté de asignar dinámicamente la cadena en su lugar con los mismos resultados de conteo de retención.

Encontré un artículo útil aquí: http://www.cocoadev.com/index.pl?NSString

FTA:

¿El NSString devuelto por @ “” necesita ser liberado, o se libera automáticamente? Ninguno. @ “” – las cadenas son de clase NSConstantString ?, y por lo tanto actúan como átomos en lisp; ellos se quedan. Es decir, si usa @ “cow” en dos lugares separados en su código, harán referencia al mismo objeto. No creo -release o -autore hace nada a ninguno de ellos.

Sin embargo, si tengo una “copia” en la propiedad, ¿no debería copiar el contenido de la memoria objective en la memoria nueva con un conteo retenido de 1? Parecería que el atributo de copia no hace nada en este caso?

 #import  int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; char *cstr = "this is ac string"; NSString *str = [[NSString alloc] initWithUTF8String:cstr]; NSLog(@"rc1: %d", [str retainCount]); [pool drain]; return 0; } 

Si ejecuta el código anterior, mostrará un conteo de retención de 1

En Cocoa, muchos objetos inmutables simplemente se retendrán cuando solicite una copia dentro de la misma zona. Si se garantiza que el objeto no cambiará (es decir, su inmutabilidad), entonces un duplicado exacto será redundante.

En Objective-C, la clase de cadena constante está separada de la clase NSString de Cocoa, aunque puede ser una subclase de NSString (no estoy muy seguro). Esta clase de cadena constante puede anular los métodos de NSObject como retain , release y dealloc para que no hagan nada, y también anular retainCount para que siempre devuelva el mismo número, UINT_MAX o menos. Esto se debe a que una cadena constante de Objective-C se crea en la memoria estática. Debe tener el comportamiento general general de un objeto Cocoa (cuando se usa Cocoa) para que se pueda agregar a matrices, usar como claves para un diccionario, etc., excepto en lo que respecta a su administración de memoria, ya que se asignó de manera diferente.

Descargo de responsabilidad: en realidad no sé de lo que estoy hablando.