127 votes

Dans quelles situations devons-nous écrire le qualificatif __autoreleasing property sous ARC?

Je suis en train de terminer le puzzle.

__strong est la valeur par défaut pour tous Objective-C retainable pointeurs d'objet comme NSObject, NSString, etc.. C'est une référence forte. ARC soldes avec un -release à la fin de la portée.

__unsafe_unretained est égale à l'ancienne. Il est utilisé pour un faible pointeur sans conserver la retainable objet.

__weak , c'est comme __unsafe_unretained sauf que c'est une auto-réinitialisation de référence faible ce qui signifie que le pointeur sera mis à zéro dès que l'objet référencé est libéré. Ceci élimine le danger de pendre les pointeurs et EXC_BAD_ACCESS erreurs.

Mais qu'est - __autoreleasing ? Je vais avoir un moment difficile de trouver des exemples pratiques sur la quand j'ai besoin d'utiliser ce qualificatif. Je crois que c'est uniquement pour les fonctions et les méthodes qui s'attendent à un pointeur de pointeur de tels que:

- (BOOL)save:(NSError**);

ou

NSError *error = nil;
[database save:&error];

qui, en vertu de l'ARC doit être déclaré ainsi:

- (BOOL)save:(NSError* __autoreleasing *);

Mais c'est trop vague et que je voudrais comprendre pleinement pourquoi. Le code des extraits que j'ai trouver de la place de l' __autoreleasing entre les deux stars, qui fait un peu bizarre pour moi. Le type est - NSError** (un pointeur de pointeur de NSError), donc pourquoi mettre l' __autoreleasing entre les étoiles et non pas simplement en face d' NSError**?

Aussi, il pourrait y avoir d'autres situations dans lesquelles je dois compter sur __autoreleasing.

70voto

Macmade Points 27414

Vous avez raison. Que la documentation officielle explique:

__autoreleasing pour désigner les arguments qui sont passés par référence (id *) et sont autoreleased sur le retour.

Tout cela est très bien expliqué dans l' ARC guide de transition.

Dans votre NSError exemple, la déclaration désigne __strong, implicitement:

NSError * e = nil;

Sera transformé à:

NSError * __strong error = nil;

Lorsque vous appelez votre save méthode:

- ( BOOL )save: ( NSError * __autoreleasing * );

Le compilateur va alors créer une variable temporaire, mis en __autoreleasing. Donc:

NSError * error = nil;
[ database save: &error ];

Sera transformé à:

NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;

Vous pouvez éviter cela en déclarant l'objet d'erreur comme __autoreleasing, directement.

39voto

Binyamin Bauman Points 447

Suite à Macmade réponse et Fier Membre de suivi de la question dans les commentaires, (l'ai aussi posté un commentaire, mais il dépasse le nombre de caractères max):

Ici, c'est pourquoi la variable qualifier d' __autoreleasing est placé entre les deux étoiles.

Pour la préface, la bonne syntaxe pour déclarer un pointeur d'objet avec un qualificatif est:

NSError * __qualifier someError;

Le compilateur va pardonner ceci:

__qualifier NSError *someError;

mais il n'est pas correct. Voir la Pomme ARC guide de transition (lire la section qui commence par "Vous devez décorer les variables correctement...").

Pour répondre à la question à portée de main: Un double pointeur ne peut pas avoir un ARC de gestion de la mémoire qualificatif, car un pointeur qui pointe vers une adresse de mémoire est un pointeur vers un type primitif, et non pas un pointeur vers un objet. Toutefois, lorsque vous déclarez un double pointeur, l'ARC ne voulez savoir ce que la gestion de la mémoire règles sont pour le deuxième pointeur. C'est pourquoi la double pointeur variables sont spécifiées sous la forme:

SomeClass * __qualifier *someVariable;

Ainsi, dans le cas de l'argument d'une méthode qui est une double NSError pointeur, le type de données est déclarée comme suit:

- (BOOL)save:(NSError* __autoreleasing *)errorPointer;

qui dit en anglais "pointeur vers un __autoreleasing NSError pointeur d'objet".

17voto

Glen Low Points 990

L' définitive spécification ARC dit que

Pour __autoreleasing objets, le nouveau pointeur est conservé, autoreleased, et stockées dans la lvalue à l'aide de primitives sémantiques.

Ainsi, par exemple, le code

NSError* __autoreleasing error = someError;

effectivement converti à

NSError* error = [[someError retain] autorelease];

... c'est pourquoi il fonctionne lorsque vous avez un paramètre NSError* __autoreleasing * errorPointer, la méthode appelée sera alors attribuer l'erreur d' *errorPointer et au-dessus de la sémantique donnera un coup de pied dans.

Vous pouvez utiliser __autoreleasing dans un contexte différent de forcer un ARC objet dans l'autorelease pool, mais ce n'est pas très utile puisque l'ARC ne semble utiliser l'autorelease pool au retour de méthode et déjà gère automatiquement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X