wake-up-neo.com

Soll ich in der init-Methode mit ARC auf self.property verweisen?

Eine kurze Frage.

wenn ich eine Immobilie und einen Ivar mit dem gleichen Namen deklariert habe:

in der .h Datei:

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

soll ich in der .m-Datei die ivar oder die Eigenschaft in der init-Methode verwenden, wenn ich ARC verwende?

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

Oder sollte ich die Eigenschaft verwenden, um die automatische Referenzzählung wie folgt zu nutzen:

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

Ich bin nicht sicher, zu welchem ​​Zeitpunkt in der Objektinitialisierung die Eigenschaften mit der Punktnotation verfügbar werden.

50
Alex Stone

Verwenden Sie den Direktzugriff in teilweise aufgebauten Zuständen unabhängig von ARC:

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

Dies liegt daran, dass self.whatever andere Nebenwirkungen auslöst, wie z. B. KVO-Benachrichtigungen (Key-Value Observing), oder Ihre Klasse implementiert (explizit) oder eine Unterklassen-Überschreibung setWhatever: - und die Ihre teilweise initialisierte Instanz anderen APIs (einschließlich der APIs) zugänglich machen könnte own), die zu Recht davon ausgehen, dass es sich um ein vollständig konstruiertes Objekt handelt.

Sie könntenmanuell überprüfen, ob eine Klasse in einem teilweise initialisierten Zustand arbeiten kann, dies erfordert jedoch viel Wartung und ist (ehrlich gesagt) unpraktisch oder unmöglich, wenn andere Personen Ihre Klasse subklassen möchten. Dies erfordert viel Zeit und Wartung, und dies hat keinen substantiellen Nutzen, insbesondere wenn Sie versuchen, den Ansatz als Konvention zu verwenden.

Die einheitliche Art und Weise, die die Richtigkeit garantiert, besteht also darin, den direkten Zugriff in teilweise aufgebauten Zuständen zu verwenden und die Verwendung der Zugriffsmechanismen zu vermeiden.

Hinweis: Ich verwende "teilweise konstruiert", da die Initialisierung nur die Hälfte des Bildes ist. -dealloc hat ähnliche Vorbehalte.

Weitere Einzelheiten dazu, warum Sie den direkten Zugriff in teilweise aufgebauten Zuständen (ARC || MRC) verwenden sollten, finden Sie hier: Initialisieren einer Eigenschaft, Punktnotation

67
justin

Nein solltest du nicht! 

Sie finden die Beschreibung warum hier
Auch Apple empfiehlt, dies nicht zu tun. Lies hier

5

Ich bin mir nicht sicher, an welcher Stelle der Objektinitialisierung die Eigenschaften mit der Punktnotation verfügbar sind.

Da die Punktnotation immer noch eine Objective-C-Methode ist (und eine C-Methode tatsächlich unter der ObjC-Methode), ist die Punktnotation oder das Aufrufen der Methode absolut sicher. GIVEN Die Methode ist für die Verarbeitung der zugrunde liegenden Typen im Speicher in vorbereitet In welchem ​​Zustand sie sich gerade befinden. Es würde immer noch die normale Regel gelten, ein nicht initiiertes (möglicherweise) Garagenspeichersegment zu vermeiden. Welches ist die stärkste Motivation für den Einsatz des ivar in der init.

Wenn Ihre Methode (getter | setter) das Speichersegment jedoch korrekt verwenden kann - unabhängig davon, ob sie zuerst geschrieben wird, bevor sie gelesen wird -, verwenden Sie auf jeden Fall Ihren Getter in der init-Methode. Ein Lazy Getter nutzt die Annahme, dass ein zu initialisierender Zeiger mit 'null' beginnt, um sich für die Initialisierung zu entscheiden. Wenn Sie den ursprünglichen Inhalt Ihres Gedächtnisses nicht annehmen können, ist das Initialisieren des ivar möglicherweise der sicherste Kurs.

Warum gilt die Regel, niemals Setter oder Getter in init zu verwenden, wenn die Methode in diesem Szenario ordnungsgemäß funktioniert?

0
user1864957