web-dev-qa-db-fra.com

Devrais-je faire référence à self.property dans la méthode init with ARC?

Une question rapide 

si j'ai une propriété et un ivar déclarés avec le même nom:

dans le fichier .h:

(Reminder*)reminder;
@property(nonatomic,strong)(Reminder*)reminder;

dans le fichier .m, dois-je utiliser l'ivar ou la propriété de la méthode init si j'utilise ARC?

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        reminder = reminder_;
    }
    return self;
}

Ou devrais-je utiliser la propriété pour bénéficier du comptage automatique des références, comme ceci:

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        self.reminder = reminder_;
    }
    return self;
}

Je ne sais pas à quel moment de l'initialisation de l'objet les propriétés deviennent accessibles avec la notation par points.

50
Alex Stone

Utilisez un accès direct dans des états partiellement construits, quel que soit l'ARC:

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        reminder = reminder_;
        // OR
        reminder = [reminder_ retain];
    }
    return self;
}

Ceci s'explique par le fait que self.whatever déclenchera d'autres effets secondaires, tels que les notifications KVO (Key-Value Observing), ou peut-être que votre classe implémentera (explicitement) ou une sous-classe écrase setWhatever: - et pourrait exposer votre instance partiellement initialisée à d'autres propre), qui supposent à juste titre qu’ils ont affaire à un objet pleinement construit.

Vous pourriez vérifier manuellement qu'une classe est capable de fonctionner dans un état partiellement initialisé, mais cela nécessite beaucoup de maintenance et est (franchement) irréalisable ou impossible lorsque d'autres personnes souhaitent sous-classer votre classe. Cela nécessite beaucoup de temps et d’entretien, et il n’ya aucun avantage matériel à le faire, surtout si vous essayez d’utiliser l’approche comme convention.

La manière uniforme qui garantit l'exactitude consiste donc à utiliser l'accès direct dans des états partiellement construits et à éviter d'utiliser les accesseurs.

Remarque: J'utilise «partiellement construit» car l'initialisation ne représente que la moitié de l'image; -dealloc a des mises en garde similaires.

Vous trouverez plus de détails sur l'utilisation de l'accès direct dans des états partiellement construits (ARC || MRC): Initialisation d'une propriété, notation par points

67
justin

Non vous ne devriez pas! 

Vous pouvez trouver une description pourquoi ici
Apple recommande également de ne pas le faire. Lire ici

5
Kostiantyn Koval

Je ne sais pas à quel moment de l'initialisation de l'objet les propriétés deviennent accessibles avec la notation par points.

Comme la notation par points est toujours une méthode Objective-C (et une méthode C actuellement dans la méthode ObjC), la notation par points, ou l'appel de la méthode, est parfaitement sûre. DONNEZ que la méthode est prête à traiter les types sous-jacents en mémoire dans quel que soit l'état dans lequel ils se trouvent. La règle normale d'éviter l'utilisation d'un segment de mémoire de garage non initié (éventuellement) s'appliquerait toujours. Quelle est la motivation la plus forte pour l'utilisation de l'ivar chez l'init.

Mais si votre méthode (getter | setter) est capable d'utiliser correctement le segment de mémoire - indépendamment du fait qu'il soit écrit avant ou avant d'être lu - utilisez alors votre getter dans la méthode init. Un Lazy getter profite de l’hypothèse selon laquelle un pointeur qu’il initialisera commencera comme «nul» pour décider de l’initialisation. Si vous ne pouvez pas assumer le contenu initial de votre mémoire, l’initialisation de ivar pourrait être la solution la plus sûre.

Pourquoi la règle de ne jamais utiliser de setters ou de getters dans init si la méthode est capable de fonctionner correctement dans ce scénario?

0
user1864957