3 votes

Comprendre les applications pratiques des pointeurs forts et faibles en Objective-C

Je viens de lire l'excellente réponse acceptée à la question suivante este question qui clarifie les différences conceptuelles entre les pointeurs forts et faibles en Objective-C, et j'essaie toujours de comprendre les différences pratiques. Je viens d'un environnement C++ où ces concepts n'existent pas, et j'ai du mal à comprendre où je pourrais utiliser l'un ou l'autre.

Quelqu'un pourrait-il fournir un exemple pratique, utilisant du code Objective-C, qui illustre les différentes utilisations des pointeurs forts et faibles ?

8voto

WDUK Points 11893

Concept

Tout est dans le nombre de retenues. L'ARC est une commodité, pour éviter aux développeurs de se soucier de conserver et de libérer manuellement. À la base, une variable forte augmentera le nombre de retenues de 1, alors qu'une variable faible ne le fera pas.

Voir ci-dessous :

@interface Test () {
    NSString* strongVariable; // Instance variables default to strong
    __weak NSString* weakVariable;
}
@end

// This has a retain count of 1, it has been allocated to memory by the user, and stored in a local variable (which is strong)
NSString* str = [[NSString alloc] initWithString:@"Test"];

// The string object will now have a retain count of 2, as the strong variable has increased its retain count
strongVariable = str;

// This weak variable does **not** increase the retain count, and as such it will still be 2
weakVariable = str;

// --

// Now, lets remove some references
// This will reduce the retain count to 1, as a strong variable has lost its link
strongVariable = nil;

// This will also reduce the retain count, as another strong variable has lost it's reference. This means the retain count is 0, and the object can now be considered to not exist
str = nil;

// What happens to weakVariable?
// Because it is referencing an object with a 0 retain count, the runtime will set the value of this variable automatically to nil (iOS 5 and above).
NSLog(@"%@", (weakVariable == nil) ? @"nil" : @"Not nil") // Will print "nil"

Vous ne pouvez pas vous retrouver dans une situation où une variable forte fait référence à un objet dont le nombre de conservations est de 0, cela va à l'encontre du concept de base d'une variable forte. Il convient de noter que, parallèlement à __weak il y a __unsafe_unretained . Cela agit comme une variable faible, sauf qu'elle n'est pas automatiquement mise à nil une fois que le compte de retenue atteint zéro, ce qui signifie qu'elle contiendra un pointeur vers une partie aléatoire de la mémoire (et se plantera si vous y accédez, vous devez la mettre à nil vous-même). La raison pour laquelle ce problème existe est due au fait qu'iOS 4 supporte l'ARC, mais pas la fonction __weak . Dans la plupart des cas, vous utiliserez __weak .

La description ci-dessus n'est qu'un aperçu pratique, vous pouvez lire beaucoup plus en profondeur en utilisant cette documentation.

Applications pratiques

Tout est __strong par défaut. Si vous voulez des valeurs faibles, vous devez utiliser __weak .

Vous utiliserez typiquement des variables faibles lorsque vous ne voulez pas conceptuellement propre un objet particulier. Si une voiture est propriétaire de son moteur et de ses roues, le conducteur ne l'est pas.

Wheel* wheel;
Engine* engine;
__weak Driver* driver;

À l'inverse, un conducteur serait propriétaire de la voiture.

Car* car;

Si la voiture appartenait au conducteur, nous aurions un conserver le cycle . La voiture possède le conducteur, et le conducteur possède la voiture. Si nous libérions l'un, qu'arriverait-il à l'autre ? L'ensemble du concept de cycles de retenue dépasse le cadre de cette question, mais vous pouvez lire à ce sujet ici.

Le même concept s'applique aux modèles de programmation, par exemple les délégués. Pour une vue de table, le contrôleur de vue possède la vue de table, mais la vue de table ne possède pas le contrôleur de vue (qui est utilisé comme un délégué).

//ViewController
UITableView* tableView;
tableView.delegate = self;     

//UITableView
@property (nonatomic, weak) id<UITableViewDelegate> delegate;

Gotchas

Une utilisation sérieuse de __weak est à quelques pâtés de maisons. Sans eux, vous risquez fort de provoquer des cycles de rétention sans vous en rendre compte. Encore une fois, cela dépasse le cadre de cette question, mais voir ici pour plus d'informations .

Analogie avec C++

Dans TR1, vous avez la possibilité d'utiliser des pointeurs partagés, ce qui vous permet de placer un objet alloué au tas dans un objet alloué à la pile, et de gérer la mémoire pour nous. Il gère la mémoire pour nous. Il le fait en utilisant le comptage de références. Chaque fois que vous passez le pointeur partagé à une autre variable, le compte de référence est incrémenté. Ceci est analogue à l'assignation à une variable forte dans Obj-C.

1voto

micazeve Points 11

D'après ce que j'ai trouvé, les pointeurs faibles sont surtout utilisés pour une relation parent-enfant, du côté enfant. En donnant au pointeur vers son parent une propriété faible, l'enfant ne possédera pas le parent et vous éviterez une relation de propriété.

Cet article m'a beaucoup aidé à comprendre ces nouveaux concepts, vous devriez y jeter un coup d'œil : http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1

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