web-dev-qa-db-ja.com

copyとmutableCopyはNSArrayとNSMutableArrayにどのように適用されますか?

copyまたはmutableCopyのいずれかで使用する場合、NSArrayNSMutableArrayの違いは何ですか?

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

// ** 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
65
fuzzygoat

copymutableCopyは異なるプロトコルで定義され(それぞれNSCopyingNSMutableCopying)、NSArrayは両方に準拠しています。 mutableCopyNSArrayに対して定義され(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になります。
  • youcannotcopyの結果に依存して変更可能です! copying NSMutableArraymayNSMutableArrayを返します。これは元のクラスですが、copying任意のNSArrayインスタンスはそうではありません。

編集: Mark Besseyの答えに照らして元のコードを再読み取りします。アレイのコピーを作成する場合、もちろん、コピーで何をするかに関係なく、オリジナルを変更できます。 copy vs mutableCopyは、新しい配列が変更可能かどうかに影響します。

編集2:NSMutableArray -copyNSMutableArrayを返します。

72
Asher Dunn

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

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

8
Mark Bessey

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

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

5
Corey Floyd
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
                                                           copyItems:YES];

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

True Deep Copyが必要な場合は、使用できますが、

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

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

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

5
robertt almeida

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

3

簡単に言うと、

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

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

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

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

2
Wizkid
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

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

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

0
Sauvik Dolui

仮定する

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

BのコンテンツはNSMutableDictionaryではなくNSDictionaryオブジェクトです。正しいですか?

0
ZYiOS