NSMutableArrayをNSArrayに変換するにはどうすればよいですか?


回答:


511
NSArray *array = [mutableArray copy];

Copy不変のコピーを作成します。Appleはさまざまな最適化を行うことができるため、これは非常に便利です。たとえばcopy、不変の配列に送信すると、オブジェクトのみが保持され、が返されますself

ガベージコレクションまたはARCを使用しない場合-copyは、オブジェクトが保持されることを覚えておいてください。


2
この答えは素晴らしいですがcopy、NSMutableArrayではなく通常のNSArray を作成するドキュメントからどのように見分けることができますか?
Dan Rosenstark、

22
@Yar:NSCopying のドキュメントを見るとそこ次のように記載されています。copyWithZone 受信オブジェクトに「不変か可変か」という考慮事項が当てはまる場合、返されるコピーは不変です。それ以外の場合、コピーの正確な性質はクラスによって決まります。
GeorgSchölly2010年

1
非常にきちんとしている-私はm5hのソリューションよりもこれを好みます。簡潔で効率的です。
David Snabel-Caunt、2011

1
私はデビッドに同意し、この応答を指すように私の応答を更新しました。
ホールスキー2013

2
@Brad:これは、可変と不変の両方の実装を持つクラスを意味します。例:NSArrayNSMutableArrayNSStringNSMutableString。しかし、たとえばNSViewController常に変更可能な状態が含まれているわけではありません。
GeorgSchölly2014

361

NSMutableArrayサブクラスであるNSArrayあなたは、常に変換が、する必要はありませんので、あなたは、アレイは、作成することができます修正することはできませんことを確認する場合はNSArrayどちらかあなたはそれが自動解放かしたいかに応じてこれらの方法を:

/* Not autoreleased */
NSArray *array = [[NSArray alloc] initWithArray:mutableArray];

/* Autoreleased array */
NSArray *array = [NSArray arrayWithArray:mutableArray];

編集: GeorgSchöllyが提供するソリューションは、特にARCがあり、autoreleaseを呼び出す必要がないため、それを行うためのより良い方法であり、非常にクリーンです。


7
(NSArray *)myMutableArrayだけを実行できますか?
Vojto 2010年

2
はい、NSMutableArrayは有効なNSArrayのサブクラスなので。
ホールスキー2010年

4
ただし、(NSArray *)へのキャストでは、(NSMutable *)までのキャストが可能です。それはそうではありませんか?
sharvey 2010年

1
@sharvey:はい、そうです。キャストしないでスーパークラスをサブクラスに直接割り当てると、警告が表示されます。通常は、不変のコピーを返します。これは、配列が実際に変更されないことを確認する唯一の方法であるためです。
GeorgSchölly2010年

1
以前は "Upcasting"(NSArray *)myMutableArrayと呼ばれ、その逆は "Downcasting"と呼ばれていました
FranciscoGutiérrezFeb

113

私は2つの主なソリューションの両方が好きです:

NSArray *array = [NSArray arrayWithArray:mutableArray];

または

NSArray *array = [mutableArray copy];

主な違いは、私はそれらに見るにはmutableArrayがnilであるとき、彼らはどのように動作するかです

NSMutableArray *mutableArray = nil;
NSArray *array = [NSArray arrayWithArray:mutableArray];
// array == @[] (empty array)

NSMutableArray *mutableArray = nil;
NSArray *array = [mutableArray copy];
// array == nil

これは間違っています。ちょうどチェックしました。[mutableArray copy]も空の配列を返します。
durazno 2016

@durazno間違いありません。テストを再確認してください。[mutableArray copy]が空の配列を返す場合、mutableArrayは空の配列である必要があります。私の答えはmutableArrayがnilの場合にのみ適用されます。
Richard Venable 2016

これは本当ですが、あなたの例ではもっと根本的な真実を見逃しているように感じます。mutableArrayをnilに割り当てたので、[mutableArray copy]に簡略化できます[nil copy]。Objective-Cでは nilに送信されるメッセージは常にnilになります。「何もない」と「何も入っていない配列」の違いを覚えておくことは重要です。
mkirk 2016

@mkirk手元にある質問から注意をそらさないようにしましょう:「NSMutableArrayをNSArrayに変換するにはどうすればよいですか?」主な解決策は2つあり、それらの主な違いは、可変配列がnilの場合の動作です。
Richard Venable 2016


5

Objective-C

以下は、NSMutableArrayをNSArrayに変換する方法です。

//oldArray is having NSMutableArray data-type.
//Using Init with Array method.
NSArray *newArray1 = [[NSArray alloc]initWithArray:oldArray];

//Make copy of array
NSArray *newArray2 = [oldArray copy];

//Make mutablecopy of array
NSArray *newArray3 = [oldArray mutableCopy];

//Directly stored NSMutableArray to NSArray.
NSArray *newArray4 = oldArray;

迅速

Swift 3.0では、新しいデータ型Arrayがあります。letキーワードを使用して配列を宣言すると、NSArrayになり、varキーワードを使用して宣言すると、NSMutableArrayになります

サンプルコード:

let newArray = oldArray as Array

Swiftの部分は完全に正しくはありません。mutable / immutable と/ の違いについては、ここここを参照してください。彼らは同じではありません。ArrayNSArrayNSMutableArray
Bruno Ely


2
NSArray *array = mutableArray;

この[mutableArray copy]アンチパターンはサンプルコード全体に渡っています。一時的で、現在のスコープの最後で割り当て解除される使い捨ての可変配列の場合は、これを停止します。

ランタイムが、範囲外になり、0にデリファレンスされ、永久に割り当て解除されようとしている可変配列の無駄なコピーを最適化できる方法はありません。


変数にを割り当てNSMutableArrayてもNSArray変換されません(これはOPの質問です)。そのような値を(たとえば、戻り値として、またはプロパティとして)公開すると、その値が予期せず変更された場合、問題のデバッグが非常に困難になる可能性があります。変更可能な値が共有されるため、これは内部と外部の両方のミューテーションに適用されます。
DavidRönnqvist2018年

その配列を変更するには、[NSMutableArray arrayWithArray:...またはそのようなものにする必要があります。
アントン・トロパシュコ、

必ずしも。NSMutableArray変数に割り当てるだけで十分です。オブジェクトが変更可能な配列になることを決して止めなかったので、オブジェクトで変更メソッドを呼び出すと、成功し、共有データが変更されます。一方、元の可変配列がコピーされて(不変配列に変更されて)NSMutableArray変数に割り当てられ、その上で変更メソッドが呼び出された場合、変更doesNotRespondToSelectorメソッド呼び出しを受け取ったオブジェクトが事実、不変であり、これらのメソッドに応答しません。
DavidRönnqvist2018年

わかりました。これは、typope変換割り当てに関するコンパイラの警告に注意を払わない開発者にとって、いくつかのメリットがあるかもしれません
Anton Tropashko

1

可変性を介して配列を作成していて、不変バージョンを返したい場合は、継承によって可変配列を「NSArray」として返すだけです。

- (NSArray *)arrayOfStrings {
    NSMutableArray *mutableArray = [NSMutableArray array];
    mutableArray[0] = @"foo";
    mutableArray[1] = @"bar";

    return mutableArray;
}

呼び出し元を "信頼"して(技術的にはまだ変更可能)戻りオブジェクトを不変のNSArrayとして扱う場合、これはよりも安価なオプションです[mutableArray copy]

アップルは同意する:

受信したオブジェクトを変更できるかどうかを判断するには、メッセージの受信者が戻り値の正式な型に依存する必要があります。たとえば、不変として型指定された配列オブジェクトを受け取った場合、それを変更しようとするべきではありません。クラスメンバーシップに基づいてオブジェクトが変更可能かどうかを判断することは、許容できるプログラミング方法ではありません。

上記の方法については、ここで詳しく説明します。

ベストプラクティス:戻り値の型がNSArrayの場合はmutableArray.copyまたはmutableArrayを返します


0

私はswift 3で答えを探していましたが、この質問は検索の最初の結果として示され、そこから答えを得たので、swift 3のコードです

let array: [String] = nsMutableArrayObject.copy() as! [String]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.