Attributs de définition de propriétés faibles et forts en Objective-C

94

Quelle est la différence entre les attributs de définition de propriétés faibles et forts dans Objective-C?

@property(retain, [weak/strong]) __attribute__((NSObject)) CFDictionaryRef myDictionary;

Quel est l'impact et le bénéfice?

J'ai entendu dire que faible n'est pas disponible sur iOS 4 et que nous devons utiliser assign.

Est-ce que faible est similaire à assigner?

kkurni
la source

Réponses:

102

Vous avez soit activé ou désactivé ARC pour un fichier particulier. Si c'est activé, vous ne pouvez pas utiliser retain release autoreleaseetc ... Au lieu de cela, vous utilisez strong weakpour les propriétés ou __strong __weak pour les variables (par défaut __strong). Strong est l'équivalent de conserver, mais ARC gérera la version pour vous.

Le seul moment où vous voudriez utiliser faible, c'est si vous vouliez éviter les cycles de rétention (par exemple, le parent conserve l'enfant et l'enfant conserve le parent de sorte qu'aucun des deux n'est jamais libéré).

La partie «pontage sans frais» (casting de NSà CF) est un peu délicate. Vous devez toujours gérer manuellement CFRelease()et CFRetain()pour les objets CF. Lorsque vous les reconvertissez en objets NS, vous devez informer le compilateur du nombre de retenues afin qu'il sache ce que vous avez fait.

Tout est ici .

Robert
la source
119

Voici des informations sur ce que je sais sur les propriétés des variables

  1. atomique // par défaut
  2. non atomique
  3. strong = conserver // par défaut
  4. faible
  5. conserver
  6. attribuer // par défaut
  7. unsafe_unretained
  8. copie
  9. lecture seulement
  10. readwrite // par défaut

Vous trouverez donc ci-dessous le lien détaillé de l'article où vous pouvez trouver tous les attributs mentionnés ci-dessus, qui vous aideront sans aucun doute. Un grand merci à toutes les personnes qui donnent les meilleures réponses ici !!

Attributs de propriété variable ou modificateurs dans iOS

01. strong (iOS4 = retenir) - il dit "gardez ceci dans le tas jusqu'à ce que je ne le pointe plus" - en d'autres termes "je suis le propriétaire, vous ne pouvez pas le désallouer avant de viser bien avec cela comme retenir "- Vous n'utilisez Strong que si vous avez besoin de conserver l'objet. - Par défaut, toutes les variables d'instance et les variables locales sont des pointeurs forts. - Nous utilisons généralement strong pour les UIViewControllers (les parents des éléments d'interface utilisateur) - strong est utilisé avec ARC et il vous aide essentiellement, en n'ayant pas à vous soucier du nombre de rétention d'un objet. ARC le libère automatiquement pour vous lorsque vous en avez terminé. L'utilisation du mot-clé strong signifie que vous possédez l'objet.

Exemple:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

02. faible (iOS4 = unsafe_unretained) - il dit "gardez ceci tant que quelqu'un d'autre le pointe fortement" - la même chose que assign, pas de conservation ou de libération - Une référence "faible" est une référence que vous ne retenez pas. - Nous utilisons généralement faible pour les IBOutlets (Childs de UIViewController) .Cela fonctionne parce que l'objet enfant n'a besoin d'exister que tant que l'objet parent existe. - une référence faible est une référence qui ne protège pas l'objet référencé de la collecte par un garbage collector. - Faible est essentiellement céder, une propriété non conservée. Sauf lorsque l'objet est désalloué, le pointeur faible est automatiquement mis à nil

Exemple :

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Expliquez : Merci à BJ Homer

Imaginez que notre objet est un chien, et que le chien veut s'enfuir (être désalloué). Les pointeurs forts sont comme une laisse sur le chien. Tant que vous avez la laisse attachée au chien, le chien ne s'enfuira pas. Si cinq personnes attachent leur laisse à un chien (cinq pointeurs puissants vers un objet), le chien ne s'enfuira pas tant que les cinq laisses ne seront pas détachées. Les pointeurs faibles, par contre, sont comme de petits enfants qui pointent le chien et disent "Regarde! Un chien!" Tant que le chien est toujours en laisse, les petits enfants peuvent toujours voir le chien et ils le montreront toujours. Cependant, dès que toutes les laisses sont détachées, le chien s'enfuit, peu importe le nombre de petits enfants qui le désignent. Dès que le dernier pointeur fort (laisse) ne pointe plus vers un objet, l'objet sera désalloué et tous les pointeurs faibles seront mis à zéro. Quand on utilise faible? La seule fois où vous voudriez utiliser faible, c'est si vous vouliez éviter les cycles de rétention (par exemple, le parent conserve l'enfant et l'enfant conserve le parent de sorte qu'aucun n'est jamais libéré).

swiftBoy
la source
1
Dans la liste initiale, je ne suis pas vraiment sûr de ce que vous entendez par «par défaut». Vous avez les deux strong=retainet assignétiquetés comme valeurs par défaut, mais cela ne peut pas être les deux.
Slipp D.Thompson
27
J'ai apprécié la comparaison du chien en laisse. Explique assez bien.
Jarrett Barnett
1
Bonne explication, bien qu'iOS n'utilise pas le ramasse-miettes. ARC! = Garbage collection (!), Ce sont des technologies différentes.
1
faible et unsafe_unretained sont différents (le premier utilise des références faibles à zéro, tandis que le second s'accroupit)
wcochran
1
J'apprends seulement iOS, mais il semble que vous ayez égaré le weaket strongdans vos exemples. Ne serait-il pas plus logique qu'un parent ait des strongréférences à ses enfants (en tant que myButtonpropriété de la UIViewControllerclasse que vous avez montrée weak) et que les enfants gardent des weakréférences à leur parent (comme la viewControllerpropriété d'une classe enfant que vous au lieu de cela défini sur strong). Par exemple, en lisant celui de Matt Neuburg, iOS 7 Programming Fundamentalsil montre qu'une classe déclarant son délégué comme propriété la maintiendra «faible, cela semble juste.
Bogdan Alexandru
2

Pour appeler les parties de la documentation référencées par Robert qui répondent explicitement à vos deux dernières questions:

// The following declaration is similar to "@property(assign) MyClass *myObject;"
// except that if the MyClass instance is deallocated,
// the property value is set to nil instead of remaining as a dangling pointer.
@property(weak) MyClass *myObject;

C'est ce qu'on appelle une référence faible de remise à zéro. Vous pouvez créer des références faibles qui ne remettent pas à zéro les références faibles en utilisant __unsafe_unretained, mais comme son nom l'indique, cela n'est généralement pas recommandé.

Aussi dans la documentation:

Weak references are not supported in Mac OS X v10.6 and iOS 4.
rimsky
la source
1
Oui, c'est correct, __unsafe_unretainedest la version ARC de assign.
Robert
2

L'utilisation claire comme du cristal de la propriété FAIBLE est la suivante:

Any control whose properties we need to change(eg:text of a label) is declared weak and as below:

@property(nonatomic,weak) IBOutlet Type *name;
Eg: @property(nonatomic,weak) IBOutlet UILabel *myLabel;
Alen Alexander
la source
1
En utilisant faible sur mes propriétés, j'obtiens un avertissement disant: "Un récepteur faible peut être réglé de manière imprévisible sur nul". J'ai vu d'autres articles indiquant que pour éviter cet avertissement, vous devez créer une référence locale forte. Et si cela est vrai, quel est l'intérêt de rendre une propriété faible, si à la fin je dois créer une référence forte?
arh
0

prenons un exemple pour élaborer plus (la réponse ci-dessus est déjà excellente), cet exemple peut-il aider un peu plus

soit deux classes A et B

//A.h

#import <Foundation/Foundation.h>
#import "B.h"

@interface A : NSObject

@property (nonatomic, strong) B *objB;

@end

@implementation A
//

@end

//B.h

    #import <Foundation/Foundation.h>
    #import "A.h"


    @interface B : NSObject

    @property strong text(nonatomic, strong) A *objA;

    @end

    @implementation B
    //

    @end

    and in main

    #import "B.h"
    #import "A.h"

    {
    A *obja =[[A alloc]init];
    B *objb =[[B alloc]init];
    A.objB=objb;
    B.objA=obja;
   }

le code ci-dessus générera un cycle de rétention car les deux sont du type fort a --------> b ---------> a

donc pour l'éviter, vous devez utiliser la propriété week de l'un d'entre eux afin qu'il se réfère chaque semaine à l'objet et ne l'augmente pas le nombre de références.

Anurag Bhakuni
la source