Objective-C Language
Gestión de la memoria
Buscar..
Conteo automático de referencias
Con el recuento automático de referencias (ARC), las inserciones del compilador retain
, release
y autorelease
donde se necesitan, por lo que no tiene que escribirlas usted mismo. También escribe métodos dealloc
para usted.
El programa de muestra de Manual Memory Management se ve así con ARC:
@interface MyObject : NSObject {
NSString *_property;
}
@end
@implementation MyObject
@synthesize property = _property;
- (id)initWithProperty:(NSString *)property {
if (self = [super init]) {
_property = property;
}
return self;
}
- (NSString *)property {
return property;
}
- (void)setProperty:(NSString *)property {
_property = property;
}
@end
int main() {
MyObject *obj = [[MyObject alloc] init];
NSString *value = [[NSString alloc] initWithString:@"value"];
[obj setProperty:value];
[obj setProperty:@"value"];
}
Aún puede anular el método dealloc para limpiar los recursos no gestionados por ARC. A diferencia de cuando se usa la administración de memoria manual, no se llama [super dealloc]
.
-(void)dealloc {
//clean up
}
Referencias fuertes y débiles.
Una referencia débil se parece a una de estas:
@property (weak) NSString *property;
NSString *__weak variable;
Si tiene una referencia débil a un objeto, entonces bajo el capó:
- No lo estás reteniendo.
- Cuando se desasigna, cada referencia se establecerá automáticamente en
nil
Las referencias a objetos son siempre fuertes por defecto. Pero puedes especificar explícitamente que son fuertes:
@property (strong) NSString *property;
NSString *__strong variable;
Una referencia fuerte significa que mientras exista esa referencia, está reteniendo el objeto.
Gestión de memoria manual
Este es un ejemplo de un programa escrito con administración de memoria manual. Realmente no deberías escribir tu código de esta manera, a menos que por alguna razón no puedas usar ARC (como si necesitas soportar 32 bits). El ejemplo evita la notación de @property
para ilustrar cómo solía tener que escribir getters y setters.
@interface MyObject : NSObject {
NSString *_property;
}
@end
@implementation MyObject
@synthesize property = _property;
- (id)initWithProperty:(NSString *)property {
if (self = [super init]) {
// Grab a reference to property to make sure it doesn't go away.
// The reference is released in dealloc.
_property = [property retain];
}
return self;
}
- (NSString *)property {
return [[property retain] autorelease];
}
- (void)setProperty:(NSString *)property {
// Retain, then release. So setting it to the same value won't lose the reference.
[property retain];
[_property release];
_property = property;
}
- (void)dealloc {
[_property release];
[super dealloc]; // Don't forget!
}
@end
int main() {
// create object
// obj is a reference that we need to release
MyObject *obj = [[MyObject alloc] init];
// We have to release value because we created it.
NSString *value = [[NSString alloc] initWithString:@"value"];
[obj setProperty:value];
[value release];
// However, string constants never need to be released.
[obj setProperty:@"value"];
[obj release];
}
Reglas de gestión de memoria cuando se utiliza el conteo manual de referencias.
Estas reglas solo se aplican si utiliza el recuento manual de referencias
Eres dueño de cualquier objeto que crees
Al llamar a un método cuyo nombre comienza con
alloc
,new
,copy
omutableCopy
. Por ejemplo:NSObject *object1 = [[NSObject alloc] init]; NSObject *object2 = [NSObject new]; NSObject *object3 = [object2 copy];
Eso significa que usted es responsable de liberar estos objetos cuando haya terminado con ellos.
Puedes tomar posesión de un objeto usando retener
Para tomar posesión de un objeto, se llama el método de retención.
Por ejemplo:
NSObject *object = [NSObject new]; // object already has a retain count of 1 [object retain]; // retain count is now 2
Esto solo tiene sentido en algunas situaciones raras.
Por ejemplo, cuando implementas un descriptor de acceso o un método init para tomar posesión:
- (void)setStringValue:(NSString *)stringValue { [_privateStringValue release]; // Release the old value, you no longer need it [stringValue retain]; // You make sure that this object does not get deallocated outside of your scope. _privateStringValue = stringValue; }
Cuando ya no lo necesite, debe renunciar a la propiedad de un objeto que posee
NSObject* object = [NSObject new]; // The retain count is now 1 [object performAction1]; // Now we are done with the object [object release]; // Release the object
No debe renunciar a la propiedad de un objeto que no posee
Eso significa que cuando no te apropiaste de un objeto, no lo liberas.
Autoreleasepool
El autoreleasepool es un bloque de código que libera cada objeto en el bloque que recibió un mensaje de autorelease.
Ejemplo:
@autoreleasepool { NSString* string = [NSString stringWithString:@"We don't own this object"]; }
Hemos creado una cadena sin tomar posesión. El
NSString
métodostringWithString:
tiene que asegurarse de que la cadena se desasigna correctamente después de que ya no es necesaria. Antes de que el método devuelva la cadena recién creada, se llama al método autorelease para que no tenga que tomar posesión de la cadena.Así es como se implementa el
stringWithString:
:+ (NSString *)stringWithString:(NSString *)string { NSString *createdString = [[NSString alloc] initWithString:string]; [createdString autorelease]; return createdString; }
Es necesario usar bloques de autoreleasepool porque a veces tienes objetos que no tienes (las cuartas reglas no siempre se aplican).
El conteo automático de referencias cuida automáticamente las reglas para que no tenga que hacerlo.