2

NSCopyingを実装しようとしている読み取り専用プロパティを持つオブジェクトがあります。「subConditions」(「SubCondition」オブジェクトを保持する)と呼ばれるmutableArrayがあります。呼び出し元が配列内のデータを変更できるようにしたいが、配列自体は変更できないようにするため、読み取り専用にしました。これは、-copyWithZone:メソッドを作成するときまで非常にうまく機能しました。

少しいじった後、私はなんとかうまくいくように見える何かを手に入れることができました。ただし、それがベストプラクティスかどうかはわかりません。これが私の-copyWithZoneの簡略版です:メソッド:

-(id)copyWithZone:(NSZone*)zone
{
    Condition *copy = [[[self class]allocWithZone:zone]init];


 NSArray *copiedArray = [[NSArray alloc]initWithArray:self.subConditions copyItems:YES];
 [copy.subConditions setArray:copiedArray];
 [copiedArray release];

    return copy;
}

これは、読み取り専用のmutableArrayをコピーするための正しい/最良の方法ですか?

4

1 に答える 1

2

[可変配列プロパティ]を読み取り専用にしました。呼び出し元が配列内のデータを変更できるようにしたいのですが、配列自体は変更できないようにするためです。

オブジェクトのプロパティの値をその知識なしに変更することは悪いモジョです。例として、オブジェクトに、どのオブジェクトが選択されているかを知るためのインデックスセットがあるとします。次に別のオブジェクトが配列からいくつかのサブ条件を削除すると、セット内のインデックスの一部またはすべてが間違ったオブジェクトを参照するか、オブジェクトをまったく参照しない可能性があります。つまり、選択したサブ条件にアクセスすると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を使用してアプリケーションのプロファイルを作成し、対象のハードウェアでオーバーヘッドが重要かどうかを判断することをお勧めします。

于 2010-06-06T12:20:08.627 に答える