copy
またはmutableCopy
のいずれかで使用する場合、NSArray
とNSMutableArray
の違いは何ですか?
これは私の理解です。それが正しいか?
// ** NSArray **
NSArray *myArray_imu = [NSArray arrayWithObjects:@"abc", @"def", nil];
// No copy, increments retain count, result is immutable
NSArray *myArray_imuCopy = [myArray_imu copy];
// Copys object, result is mutable
NSArray *myArray_imuMuta = [myArray_imu mutableCopy];
// Both must be released later
// ** NSMutableArray **
NSMutableArray *myArray_mut = [NSMutableArray arrayWithObjects:@"A", @"B", nil];
// Copys object, result is immutable
NSMutableArray *myArray_mutCopy = [myArray_mut copy];
// Copys object, result is mutable
NSMutableArray *myArray_mutMuta = [myArray_mut mutableCopy];
// Both must be released later
copy
とmutableCopy
は異なるプロトコルで定義され(それぞれNSCopying
とNSMutableCopying
)、NSArray
は両方に準拠しています。 mutableCopy
はNSArray
に対して定義され(NSMutableArray
だけでなく)、元々不変の配列の可変コピーを作成できます。
// create an immutable array
NSArray *arr = [NSArray arrayWithObjects: @"one", @"two", @"three", nil ];
// create a mutable copy, and mutate it
NSMutableArray *mut = [arr mutableCopy];
[mut removeObject: @"one"];
概要:
mutableCopy
の結果に依存して変更可能にすることができます。配列の場合、結果はNSMutableArray
になります。copy
の結果に依存して変更可能です! copy
ing NSMutableArray
mayはNSMutableArray
を返します。これは元のクラスですが、copy
ing任意のNSArray
インスタンスはそうではありません。編集: Mark Besseyの答えに照らして元のコードを再読み取りします。アレイのコピーを作成する場合、もちろん、コピーで何をするかに関係なく、オリジナルを変更できます。 copy
vs mutableCopy
は、新しい配列が変更可能かどうかに影響します。
編集2:NSMutableArray -copy
はNSMutableArray
を返します。
CopyとmutableCopyの動作方法を誤って解釈したに違いないと思います。最初の例では、myArray_COPYはmyArrayの不変のコピーです。コピーを作成したら、元のmyArrayのコンテンツを操作できますが、myArray_COPYのコンテンツには影響しません。
2番目の例では、myArrayの可変コピーを作成します。つまり、アレイのいずれかのコピーを、他に影響を与えずに変更できます。
最初の例を変更してmyArray_COPYからオブジェクトを挿入/削除しようとすると、期待どおりに失敗します。
おそらく、典型的なユースケースについて考えることは助けになるでしょう。多くの場合、NSArray *
パラメータ。基本的には後で使用するために保存します。次の方法でこれを行うことができます。
- (void) doStuffLaterWith: (NSArray *) objects {
myObjects=[objects retain];
}
...しかし、NSMutableArrayを引数としてメソッドを呼び出すことができるという問題があります。配列を作成したコードは、doStuffLaterWith:メソッドが呼び出されたときと、後で値を使用する必要があるときとの間で配列を操作する場合があります。マルチスレッドアプリでは、配列の内容を変更することもできます繰り返し処理中。これにより、いくつかの興味深いバグが発生する可能性があります。
代わりにこれを行う場合:
- (void) doStuffLaterWith: (NSArray *) objects {
myObjects=[objects copy];
}
..その後、コピーはメソッドが呼び出されたときに配列の内容のスナップショットを作成します。
「copy」メソッドは、NSCopyingプロトコルcopyWithZoneの実装によって作成されたオブジェクトを返します。
NSStringにコピーメッセージを送信する場合:
NSString* myString;
NSString* newString = [myString copy];
戻り値はNSStringになります(変更不可)
MutableCopyメソッドは、NSMutableCopyingプロトコルのmutableCopyWithZoneを実装して作成されたオブジェクトを返します。
送信することにより:
NSString* myString;
NSMutableString* newString = [myString mutableCopy];
戻り値[〜#〜] will [〜#〜]は変更可能です。
すべての場合において、オブジェクトはプロトコルを実装する必要があります。これは、新しいコピーオブジェクトを作成し、それを返すことを示します。
NSArrayの場合、浅いコピーと深いコピーに関して余分なレベルの複雑さがあります。
NSArrayの浅いコピーは、元の配列のオブジェクトへの参照のみをコピーし、新しい配列に配置します。
結果は次のとおりです。
NSArray* myArray;
NSMutableArray* anotherArray = [myArray mutableCopy];
[[anotherArray objectAtIndex:0] doSomething];
元の配列のインデックス0のオブジェクトにも影響します。
ディープコピーは、配列に含まれる個々のオブジェクトを実際にコピーします。これは、個々のオブジェクトに「copyWithZone:」メッセージを送信することにより行われます。
NSArray* myArray;
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray
copyItems:YES];
可変オブジェクトのコピーに関する誤った仮定を削除するように編集されました
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
copyItems:YES];
anotherArray
を2レベルの深さまでコピーしたoldArray
を作成します。 oldArray
のオブジェクトが配列の場合。これは通常、ほとんどのアプリケーションで当てはまります。
True Deep Copyが必要な場合は、使用できますが、
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject: oldArray]];
これにより、各レベルで元のオブジェクトの可変性を保持したまま、すべてのレベルが実際にコピーされます。
ロバートクラレンスダルメイダ、バンガロール、インド。
作成した配列の新しいコピーではなく、元の配列でaddObjectとremoveObjectAtIndexを呼び出しています。 copy vs mutableCopyの呼び出しは、元のオブジェクトではなく、オブジェクトの新しいコピーの可変性にのみ影響します。
簡単に言うと、
コピー(どちらの場合も)とは、元の配列へのオブジェクト参照(つまり、同じ(元の)オブジェクトがコピーで参照されている)が「読み込まれた」新しい配列を取得することを意味します。
MutableCopyに新しいオブジェクトを追加すると、それらはmutableCopyに固有のものになります。 mutableCopyからオブジェクトを削除すると、それらは元の配列から削除されます。
どちらの場合も、コピーが作成された時点での元のアレイのスナップショットと考えてください。
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.
これらのコピーのものの戻り値の型を知る必要があり、戻り値が割り当てられる新しいオブジェクトを宣言している間は、不変または可変のものでなければなりません。そうしないと、コンパイラはエラーを表示します。
コピーされたオブジェクトは、新しいオブジェクトを使用して変更することはできません。これらは現在、2つの異なるオブジェクトです。
仮定する
NSArray *A = xxx; // A with three NSDictionary objects
NSMutableArray *B = [A mutableCopy];
BのコンテンツはNSMutableDictionaryではなくNSDictionaryオブジェクトです。正しいですか?