Objectif C - ARC - Quand utiliser @autoreleasepool
J'ai lu un peu sur l'ARC et j'ai vu ceci:
@interface Address : NSObject {
@public
NSString *city;
}
@end
@implementation Address
- (Address*) init: (NSString*) c {
city = c;
return self;
}
- (void) dealloc {
NSLog(@"Destroying address: %@", city);
}
@end
@interface Customer : NSObject {
NSString *name;
Address *addr;
}
@end
@implementation Customer
- (Customer*) init: (NSString*) n withAddress: (Address*) a {
//Note 1: Automatic retain on assignment
name = n;
addr = a;
return self;
}
- (void) dealloc {
NSLog(@"Destroying: %@", name);
//Note 2: Automatic release of member variables
}
@end
Customer* objectReturnTest() {
NSString * n = [[NSString alloc] initWithString: @"Billy Bob"];
Address * a = [[Address alloc] init: @"New York City"];
Customer *c = [[Customer alloc] init: n withAddress: a];
//Note 3: ARC will put the returned object in autorelease pool.
return c;
}
A couple of basic things to note here. As "Note 1" says, when an object is assigned to a variable, a call to retain is made automatically. This increments the reference count. As "Note 2" says, when an object is destroyed, all member variable objects are released for you. You no longer have to do that from the dealloc method.
Finally, when a method returns a newly created object, ARC will put the returned object in an autorelease pool. This is stated in "Note 3".
Now, let’s use the code.
int main (int argc, const char * argv[])
{
NSString * n = [[NSString alloc] initWithString: @"Johnny Walker"];
Address * a = [[Address alloc] init: @"Miami"];
Customer *c = [[Customer alloc] init: n withAddress: a];
NSLog(@"Before force release");
c = nil; //Force a release
NSLog(@"After force release");
@autoreleasepool {
Customer *c2 = objectReturnTest();
}
NSLog(@"After autorelease pool block.");
return 0;
}
The log output from this code will be:
Before force release
Destroying: Johnny Walker
After force release
Destroying: Billy Bob
Destroying address: New York City
After autorelease pool block.
Destroying address: Miami
A couple of things to note here. See how force release works. We set a variable to nil. ARC immediately releases the reference count. This causes the Customer object "Johnny Walker" to get destroyed. But, the member Address object "Miami" doesn’t get destroyed. This object gets destroyed at the very end of the main method. This is an extremely odd and non-intuitive behavior. Technically, this is not a memory leak, but, in reality member variables can pile up and take up a lot of memory. This is just as bad as memory leak.
The object return test works as expected. Customer "Billy Bob" is put in auto release pool. At the end of the @autoreleasepool block, the pool is drained and the object is released.
À la recherche à la présente partie;
int main (int argc, const char * argv[])
{
NSString * n = [[NSString alloc] initWithString: @"Johnny Walker"];
Address * a = [[Address alloc] init: @"Miami"];
Customer *c = [[Customer alloc] init: n withAddress: a];
NSLog(@"Before force release");
c = nil; //Force a release
NSLog(@"After force release");
@autoreleasepool {
Customer *c2 = objectReturnTest();
}
NSLog(@"After autorelease pool block.");
return 0;
}
Quand il ne c = nil;
ne devrait pas c a n tous être détruits? Pourtant, il est dit que la sortie est seulement que ce n est détruit..
Quelqu'un peut m'expliquer pourquoi?
Et il dit que le résultat est aussi mauvais que d'une fuite de mémoire, alors comment voulez-vous résoudre ce problème?
Et une dernière question, quand devez-vous utiliser @autoreleaasepool?
OriginalL'auteur user1021085 | 2012-02-11
Vous devez vous connecter pour publier un commentaire.
en ligne
un
Customer
instance est libérée, parce que personne n'est à retenir, pour un résultat à la sortie estmais
n
eta
n'ont pas été libéré parce qu'ils restent dans le champ d'application etnil
n'a pas été affecté.et je ne pense pas que ce soit tout type de fuite de mémoire
vous n'avez normalement pas besoin d'utiliser @autorelasepool sauf si vous faites quelque chose comme cela
De 1000000 NSString seront attribués au cours de la boucle. Ils seront libérées après le renvoi de la méthode (en fait, après cette runloop) mais déjà consomment trop de mémoire. Par conséquent, il devrait remplacer à
vous devriez lire ceci pour en savoir plus sur la gestion de la mémoire
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-CJBFBEDI
Et juste une chose, si vous souhaitez une fonction pour renvoyer quelque chose, comme une chaîne de caractères? Avez-vous juste de ne NSString *a = @"hey"; return a;? N'est-ce pas être libéré et vous ne serez pas en mesure d'enregistrer la valeur ?
stringWithFormat:] c'est même comme
[[[NSString alloc] initWithFormat:] autorelease]
c'est donc un autoreleased objet. L'ARC peut occuper de tout (sauf si vous travaillez avec __dangereuse_consignes de pointeur ou de l' __pont en fonte) afin de conserver et d'autorelease la chaîne et il ne sera pas libéré jusqu'à la prochaine runloopCe que je ne comprends pas, c'est que dans la deuxième exécution de la boucle, la chaîne est orientée vers une nouvelle chaîne et la précédente est prêt à être dealloced. Pourquoi faut-il attendre jusqu'à la fin de la méthode pour le faire? Qu'est-ce que l'utilisation de tous ceux pointerless chaînes dans la mémoire. Il semble un peu bizarre que nous avons pour forcer ce comportement en ajoutant un @autoreleasepool.
parce que c'est autoreleased objet (
[[[NSString alloc] init] autorelease]
) où l'autorelease pool de prendre la responsabilité de gratuit. sans@autoreleasepool
vous seul code sera exécuté dans la boucle et de l'autorelease n'aura pas de chance pour libérer de la mémoire.OriginalL'auteur Bryan Chen
Évident de la differense entre le nom et l'adresse que vous créez un Objet d'Adresse pour l'adresse et NSString pour nom. Dans l'adresse de l'objet c'est @public. Cette meeas la NSString est hors de portée quand le client est libéré, mais pas l'adresse de l'objet, il reste toujours le souvenir de l'adresse donnée à la @public NSString *ville lorsque vous relâchez la clientèle.
Ainsi, lorsque vous appelez cette valeur publique pour l'adresse, il est toujours là, mais pas la NSString pour nom. Pour y remédier, vous pouvez soit supprimer l'interface de l'Adresse de l'Objet, qui dégage à la fois une valeur ou vous pouvez créer une interface pour le nom au lieu d'utiliser NSString.
OriginalL'auteur Odd-Arne Dahle