web-dev-qa-db-ja.com

Objective-C / iPhone開発での遅延インスタンス化

簡単な質問...まあ、Objective-Cではすべてのプロパティがnilで始まり​​、nilにメッセージを送信しても何も起こらないことを理解しているため、[[Class alloc] init]を使用して初期化する必要があります。新しく作成されたプロパティにメッセージを送信する前。ただし、このプロパティにメッセージを送信しない場合や、self.property = somethingを使用してプロパティを設定した場合はどうなりますか?これらの場合にもinitを割り当てる必要がありますか?また、ストーリーボードからドラッグアウトしたUILabelプロパティなど、UIプロパティもnilから始まりますか?これらにはalloc initが必要ですか?

答えてくれたみんなに感謝

26
user1452574

Stunnerは、すでに作成されたinitオブジェクトを割り当てる必要がないことを説明するのに優れた仕事をしました。

しかし、それが存在しないオブジェクトである場合、どこに作成しますか?あなたがあなたの投稿でそれを述べたので私が言及する非常に一般的なパターンは遅延インスタンス化です。

したがって、NSMutableArrayプロパティが必要です。使用する前に、いくつかのメソッドでinitを割り当てることができますが、「配列が必要になる前にそのメソッドが呼び出されるのか」について心配する必要があります。または「誤ってもう一度呼び出して、再初期化しますか?」

したがって、フェイルセーフの場所は、プロパティのゲッター内にあります。プロパティにアクセスするたびに呼び出されます。

.h
@property (nonatomic, strong) NSMutableArray* myArray;

.m
@synthesize myArray = _myArray;

- (NSMutableArray*)myArray
{
    if (!_myArray) {
        _myArray = [[NSMutableArray alloc] initWithCapacity:2];
    }
    return _myArray;
}

そのプロパティにアクセスするたびに、「myArrayは存在しますか?存在しない場合は作成します。存在する場合は、持っているものを返します」と表示されます。

さらに、このデザインパターンの追加の利点は、必要に応じてリソースを作成するのではなく、たとえば、ビューコントローラーの読み込み時やアプリの起動時にリソースを一度に作成する場合です。秒。

39
Jason C. Howlin

現実はあなたがするときですself.myProperty = [[Class alloc] init]、プロパティを初期化していません。むしろ、プロパティ(実際にはポインタ)にポイントするように指示するオブジェクトを初期化しています。したがって、既に割り当てられて初期化されているオブジェクトがある場合は、再度alloc/initを実行する必要はなく、self.myProperty = object;

UIプロパティはnilとして開始しません。これは、インターフェイスビルダーで要素を追加すると、ビューが追加した要素を所有し、これらのオブジェクトが自動的に初期化されるためです。これは、IBOutletを作成してそれらをいくつかのプロパティに接続する場合、alloc/initを実行する必要がないことを意味します。

これがお役に立てば幸いです。

4
Kaan Dedeoglu

ストーリーボードの経験はありませんが、xibファイルを使用してオブジェクトを作成する場合、ビューコントローラーにxibファイルを使用するように指示すると、すべてのオブジェクトが適切にインスタンス化されます。したがって、コードでそれらのオブジェクトを割り当て/初期化することについて心配する必要はありません。

self.property = <something>の使用に関しては、somethingが何であるかによって異なります。何かが既存のオブジェクトの種類である場合、self.property = ...構文はプロパティの新しい値を適切に保持、コピー、割り当てなどするプロパティのセッターメソッドを呼び出すため、そのオブジェクトに対してalloc initを実行する必要はありません。

これで、あらゆる種類の既存のオブジェクトを、割り当て/初期化されたオブジェクト、またはコンビニエンスメソッド(NSStringのstringWithFormat:など)から取得した自動解放オブジェクトにすることができます。

Kaan Dedeogluが指摘したように、self.property = ...構文はivarをメモリ内のオブジェクトにポイント(および保持)します。まだインスタンス化されていない場合は、そのオブジェクトを初期化する必要があります。

1
Stunner

いいえ、initメソッドでプロパティを[[Class alloc] initに初期化する必要はありません。

ただし、わかりやすくするために、initメソッドで明示的にNilに設定することをお勧めします。

0
grillp