How do I convert NSMutableArray to NSArray?

202,568

Solution 1

NSArray *array = [mutableArray copy];

Copy makes immutable copies. This is quite useful because Apple can make various optimizations. For example sending copy to a immutable array only retains the object and returns self.

If you don't use garbage collection or ARC remember that -copy retains the object.

Solution 2

An NSMutableArray is a subclass of NSArray so you won't always need to convert but if you want to make sure that the array can't be modified you can create a NSArray either of these ways depending on whether you want it autoreleased or not:

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

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

EDIT: The solution provided by Georg Schölly is a better way of doing it and a lot cleaner, especially now that we have ARC and don't even have to call autorelease.

Solution 3

I like both of the 2 main solutions:

NSArray *array = [NSArray arrayWithArray:mutableArray];

Or

NSArray *array = [mutableArray copy];

The primary difference I see in them is how they behave when mutableArray is nil:

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

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

Solution 4

you try this code---

NSMutableArray *myMutableArray = [myArray mutableCopy];

and

NSArray *myArray = [myMutableArray copy];

Solution 5

Objective-C

Below is way to convert NSMutableArray to 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

In Swift 3.0 there is new data type Array. Declare Array using let keyword then it would become NSArray And if declare using var keyword then it's become NSMutableArray.

Sample code:

let newArray = oldArray as Array
Share:
202,568
marcy
Author by

marcy

Updated on October 11, 2020

Comments

  • marcy
    marcy over 3 years

    How do I convert NSMutableArray to NSArray in ?

  • Dan Rosenstark
    Dan Rosenstark almost 14 years
    this answer is great, but how can I tell from the docs that copy creates a normal NSArray and not an NSMutableArray?
  • Vojto
    Vojto over 13 years
    Can I just do (NSArray *) myMutableArray ?
  • hallski
    hallski over 13 years
    Yes, as NSMutableArray is a subclass of NSArray that is valid.
  • sharvey
    sharvey over 13 years
    However, casting to (NSArray *) still allows a cast back up to (NSMutable *). Ain't that the case?
  • Stefan
    Stefan over 13 years
    @sharvey: Yes, that's correct. You'll get a warning if you don't cast but assign a superclass to a subclass directly. Usually, you want to return a immutable copy, because that's the only way to be sure, that your array really won't get modified.
  • Stefan
    Stefan over 13 years
    @Yar: You look at the documentation of NSCopying It states there: copyWithZone The copy returned is immutable if the consideration “immutable vs. mutable” applies to the receiving object; otherwise the exact nature of the copy is determined by the class.
  • David Snabel-Caunt
    David Snabel-Caunt over 12 years
    Very neat - I prefer this to m5h's solution. Both terse and more efficient.
  • Francisco Gutiérrez
    Francisco Gutiérrez about 11 years
    Formerly That's known as "Upcasting" (NSArray *) myMutableArray and the inverse is called "Downcasting"
  • hallski
    hallski about 11 years
    I agree David, updated my response to point to this response.
  • Bradley Thomas
    Bradley Thomas over 9 years
    @Georg I see lots of up votes for your comment, but frankly I don't have a clue what that Apple doc comment actually means. How does one determine if "the consideration immutable vs mutable applies to the receiving object"?
  • Stefan
    Stefan over 9 years
    @Brad: That just means classes that have both mutable and immutable implementations. E.g. NSArray & NSMutableArray, NSString & NSMutableString. But not for example NSViewController which always contains mutable state.
  • Ky -
    Ky - about 8 years
    What does this do that the others don't do?
  • durazno
    durazno almost 8 years
    This is so wrong. Just checked. [mutableArray copy] also returns an empty array.
  • Richard Venable
    Richard Venable almost 8 years
    @durazno It is not wrong. Double check your test. If [mutableArray copy] is returning an empty array, then mutableArray must have been an empty array. My answer only applies when mutableArray is nil.
  • mkirk
    mkirk almost 8 years
    Although this is true, I feel like you're missing a more fundamental truth in your example. Since you've assigned mutableArray to be nil, [mutableArray copy] can be simplified to [nil copy]. In objective-c any message sent to nil will always be nil. It's important to remember the distinction between "nothing" and "an array with nothing in it".
  • Richard Venable
    Richard Venable almost 8 years
    @mkirk Let's not distract from the question at hand: "How do I convert NSMutableArray to NSArray?" There are 2 primary solutions, and the primary difference between them is how they behave when the mutable array is nil.
  • sleighty
    sleighty almost 6 years
    The Swift part is not entirely right. See here and here for the difference between mutable/immutable Arrays and NSArray/NSMutableArrays. They are not the same.
  • David Rönnqvist
    David Rönnqvist over 5 years
    Assigning an NSMutableArray to an NSArray variable will not covert it (which is what the OP's question is about). Exposing such a value (for example as a return value or as a property) could result in very hard to debug issues if that value was unexpectedly mutated. This applies to both internal and external mutations since the mutable value is shared.
  • Anton Tropashko
    Anton Tropashko over 5 years
    To mutate that array you'd have to [NSMutableArray arrayWithArray:... or something like that.
  • David Rönnqvist
    David Rönnqvist over 5 years
    Not necessarily. Simply assigning it to a NSMutableArray variable is enough. Since the object never stopped being a mutable array, calling mutating methods on it will succeed and mutate the shared data. If on the other hand the original mutable array was copied—changing it to an immutable array—and then assigned to a NSMutableArray variable and had mutating methods called on it, those calls would fail with doesNotRespondToSelector errors because the object that received the mutating method call is in fact immutable and doesn't respond to those methods.
  • Anton Tropashko
    Anton Tropashko over 5 years
    ok, this might have some merit for developers that don't heed the compiler warning about tyope conversion assigments