web-dev-qa-db-ja.com

ARCのinitメソッドでself.propertyを参照する必要がありますか?

簡単な質問です。

同じ名前で宣言されたプロパティとivarがある場合:

.hファイル内:

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

.mファイルで、ARCを使用している場合、initメソッドでivarまたはプロパティを使用する必要がありますか?

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

または、このプロパティを使用して、次のように自動参照カウントのメリットを得る必要があります。

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

オブジェクトの初期化のどの時点でプロパティがドット表記でアクセス可能になるかはわかりません。

50
Alex Stone

ARCに関係なく、部分的に構築された状態で直接アクセスを使用します。

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

これは、self.whateverがKey-Value Observing(KVO)通知などの他の副作用をトリガーしたり、クラスが(明示的に)実装したり、サブクラスがsetWhatever:をオーバーライドしたりするためです。他のAPIへの初期化されたインスタンス(独自のものを含む)。完全に構築されたオブジェクトを処理していることを正しく想定しています。

couldは、クラスが部分的に初期化された状態で動作できることを手動で確認しますが、多くのメンテナンスが必要であり、他の人々はあなたのクラスをサブクラス化したいと思っています。これには多くの時間とメンテナンスが必要であり、特にこの方法を慣例として使用しようとする場合、それを行うことの実質的な利点はありません。

したがって、正確性を保証する統一された方法は、部分的に構築された状態で直接アクセスを使用し、アクセサの使用を避けることです。

注:初期化は全体像の半分に過ぎないため、「部分的に構成された」を使用しています。 -deallocにも同様の警告があります。

部分的に構成された状態(ARC || MRC)で直接アクセスを使用する必要がある理由の詳細は、次のとおりです。 プロパティの初期化、ドット表記

67
justin

いいえ、すべきではありません。

理由の説明を見つけることができます ここ
またAppleしないことをお勧めします。 こちらをお読みください

5

オブジェクトの初期化のどの時点でプロパティがドット表記でアクセス可能になるかはわかりません。

ドット表記は依然としてObjective-Cメソッド(および実際にはObjCメソッドの下のCメソッド)であるため、ドット表記、またはメソッドの呼び出しは完全に安全です。初期化されていない(場合によっては)ガレージメモリセグメントの使用を回避することに関する通常の規則が引き続き適用されます。これは、initでivarを使用する最大の動機です。

ただし、メソッド(getter | setter)がメモリセグメントを正しく使用できる場合(最初に書き込まれる前に読み込まれるかどうかに関係なく)、必ずinitメソッドでゲッターを使用してください。レイジーゲッターは、初期化するポインターが「nil」として開始するという仮定を利用して、初期化の実行を決定します。メモリの初期内容を想定できない場合は、ivarを初期化するのが最も安全な方法です。

メソッドがこのシナリオで正しく動作する場合、initでセッターまたはゲッターを使用しないというルールがあるのはなぜですか?

0
user1864957