66

とのいずれかで使用した場合copyの違いは何ですか?mutableCopyNSArrayNSMutableArray

これが私の理解です。それが正しいか?

// ** 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
4

8 に答える 8

73

copyおよびmutableCopyは異なるプロトコル(NSCopyingおよびNSMutableCopying、それぞれ)で定義されており、NSArray両方に準拠しています。は(だけでなく)mutableCopyに対して定義されており、元々不変の配列の可変コピーを作成できます。NSArrayNSMutableArray

// 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すると、NSMutableArray 返される場合がありますが、任意のインスタンスを実行しても返されません。NSMutableArraycopyNSArray

編集: Mark Besseyの答えに照らして、元のコードを読み直してください。もちろん、配列のコピーを作成するときは、コピーをどのように処理するかに関係なく、元の配列を変更できます。copyvsは、新しい配列mutableCopyが変更可能かどうかに影響します。

編集2:NSMutableArray -copyを返す私の(誤った)仮定を修正しましたNSMutableArray

于 2010-01-04T21:11:06.993 に答える
9

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];
}

次に、コピーは、メソッドが呼び出されたときに配列の内容のスナップショットを作成します。

于 2010-01-04T21:12:32.090 に答える
5

「copy」メソッドは、NSCopyingプロトコルcopyWithZoneを実装することによって作成されたオブジェクトを返します。

NSStringにコピーメッセージを送信する場合:

NSString* myString;

NSString* newString = [myString copy];

戻り値はNSString(変更不可)になります


mutableCopyメソッドは、NSMutableCopyingプロトコルのmutableCopyWithZoneを実装することによって作成されたオブジェクトを返します。

送信することによって:

NSString* myString;

NSMutableString* newString = [myString mutableCopy];

戻り値は変更可能です。


すべての場合において、オブジェクトはプロトコルを実装する必要があります。これは、オブジェクトが新しいコピーオブジェクトを作成し、それを返すことを意味します。


NSArrayの場合、浅いコピーと深いコピーに関してさらに複雑になります。

NSArrayの浅いコピーは、元の配列のオブジェクトへの参照のみをコピーし、それらを新しい配列に配置します。

結果は次のとおりです。

NSArray* myArray;

NSMutableArray* anotherArray = [myArray mutableCopy];

[[anotherArray objectAtIndex:0] doSomething];

元の配列のインデックス0のオブジェクトにも影響します。


ディープコピーは、実際には配列に含まれる個々のオブジェクトをコピーします。これは、個々のオブジェクトに「copyWithZone:」メッセージを送信することによって行われます。

NSArray* myArray;

NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray
                                                       copyItems:YES];

可変オブジェクトのコピーに関する私の間違った仮定を削除するために編集されました

于 2010-01-04T21:25:47.417 に答える
5
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
                                                           copyItems:YES];

深さ2レベルまでanotherArrayのコピーであるものを作成します。oldArrayのオブジェクトがoldArray配列の場合。これは通常、ほとんどのアプリケーションに当てはまります。

真のディープコピーが必要な場合は、

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
    [NSKeyedArchiver archivedDataWithRootObject: oldArray]];

これにより、すべてのレベルが実際にコピーされ、各レベルで元のオブジェクトの可変性が保持されます。

ロバートクラレンスダルメイダ、バンガロール、インド。

于 2011-09-02T16:06:54.873 に答える
3

作成した新しい配列ではなく、元の配列でaddObjectとremoveObjectAtIndexを呼び出しています。copyとmutableCopyの呼び出しは、元のオブジェクトではなく、オブジェクトの新しいコピーの可変性にのみ影響します。

于 2010-01-04T22:56:23.287 に答える
2

簡単に言えば、

  • copyは、配列の不変の(変更できない)コピーを返します。
  • mutableCopyは、配列の可変(変更可能)コピーを返します。

コピー(どちらの場合も)は、元の配列へのオブジェクト参照が「入力」された新しい配列を取得することを意味します(つまり、同じ(元の)オブジェクトがコピーで参照されます。

mutableCopyに新しいオブジェクトを追加すると、それらはmutableCopyに固有のものになります。mutableCopyからオブジェクトを削除すると、元の配列からオブジェクトが削除されます。

どちらの場合も、コピーは、コピーが作成されたときの元のアレイのスナップショットと考えてください。

于 2014-07-05T11:57:02.417 に答える
0

推定

NSArray *A = xxx; // A with three NSDictionary objects
NSMutableArray *B = [A mutableCopy]; 

BのコンテンツはNSMutableDictionaryではなくNSDictionaryオブジェクトですよね?

于 2011-05-12T04:28:36.963 に答える
0
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

これらのコピーの戻りタイプを知っている必要があります。新しいオブジェクトを宣言するときに、どのオブジェクトに戻り値が割り当てられるかは、不変または可変でなければなりません。そうでない場合、コンパイラはエラーを表示します。

コピーされたオブジェクトは、新しいオブジェクトを使用して変更することはできません。これらは、完全に2つの異なるオブジェクトになりました。

于 2013-08-07T06:28:30.247 に答える