[可変配列プロパティ]を読み取り専用にしました。呼び出し元が配列内のデータを変更できるようにしたいのですが、配列自体は変更できないようにするためです。
オブジェクトのプロパティの値をその知識なしに変更することは悪いモジョです。例として、オブジェクトに、どのオブジェクトが選択されているかを知るためのインデックスセットがあるとします。次に別のオブジェクトが配列からいくつかのサブ条件を削除すると、セット内のインデックスの一部またはすべてが間違ったオブジェクトを参照するか、オブジェクトをまったく参照しない可能性があります。つまり、選択したサブ条件にアクセスするとNSOutOfRangeExceptionが発生します。
これは悪い習慣であり、解決策は逆の習慣に切り替えることです。これは決してこれを行わないことです。所有者に変更を加えるように指示して、所有するアレイに常に変更を加えます。または、少なくとも、変更を適用して独自のアレイを作成し、それを元のアレイの所有者に示します。所有者(条件)は、後者のソリューションでは、おそらくそのインデックスセットを一掃し、選択を忘れますが、それでも例外を発生させるよりはましです。
プロパティのタイプをNSMutableArrayからNSArrayに変更すると、NSMutableArrayのみがに応答するため、上記のコードは警告を表示するはずsetArray:
です。(アクセサが自動解放されたコピーではなく可変配列を返すことを前提として、コードは引き続き機能subConditions
しますが、コンパイラはそれについて警告を出します。)配列をテーブルから変更すると、Conditionクラスが提供できるようにする方法が問題になります。コピーされたサブ条件のコピーされた配列を含むConditionインスタンスのコピー。ただし、他のクラスには許可されません。
1つの解決策は、新しい配列をコピーのインスタンス変数に直接格納することです。通常、これも悪いモジョですが、この特定のコンテキスト(copyWithZone:
影響を受けるオブジェクトがコピーである場合)では、これは適切な数少ないケースの1つです。これを行うには、メンバーへのポインター演算子を使用します。
copy->subConditions = [[NSMutableArray alloc]initWithArray:self.subConditions copyItems:YES];
もう1つの解決策は、クラス拡張readwrite
を使用して、クラスの実装ファイル内としてプロパティを再宣言することです。(readonly
宣言はクラスのヘッダーファイルに保持します。)次に、プロパティアクセスメッセージを使用できます。
copy.subConditions = [[[NSArray alloc]initWithArray:self.subConditions copyItems:YES]autorelease];
ivarへの直接アクセスがわずかに高速であることを除いて、どちらか一方を推奨することはあまりありません。プロパティバージョンは一時配列を作成し、アクセサーメッセージを送信して、新しい条件にその配列のコピーを作成させます。最初にプロパティアクセスバージョンを使用してから、Instrumentsを使用してアプリケーションのプロファイルを作成し、対象のハードウェアでオーバーヘッドが重要かどうかを判断することをお勧めします。