How do I convert NSMutableArray to NSArray? - objective-c

How do I convert NSMutableArray to NSArray in objective-c?

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.

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.

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

you try this code---
NSMutableArray *myMutableArray = [myArray mutableCopy];
and
NSArray *myArray = [myMutableArray copy];

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

In objective-c :
NSArray *myArray = [myMutableArray copy];
In swift :
var arr = myMutableArray as NSArray

NSArray *array = mutableArray;
This [mutableArray copy] antipattern is all over sample code. Stop doing so for throwaway mutable arrays that are transient and get deallocated at the end of the current scope.
There is no way the runtime could optimize out the wasteful copying of a mutable array that is just about to go out of scope, decrefed to 0 and deallocated for good.

If you're constructing an array via mutability and then want to return an immutable version, you can simply return the mutable array as an "NSArray" via inheritance.
- (NSArray *)arrayOfStrings {
NSMutableArray *mutableArray = [NSMutableArray array];
mutableArray[0] = #"foo";
mutableArray[1] = #"bar";
return mutableArray;
}
If you "trust" the caller to treat the (technically still mutable) return object as an immutable NSArray, this is a cheaper option than [mutableArray copy].
Apple concurs:
To determine whether it can change a received object, the receiver of a message must rely on the formal type of the return value. If it receives, for example, an array object typed as immutable, it should not attempt to mutate it. It is not an acceptable programming practice to determine if an object is mutable based on its class membership.
The above practice is discussed in more detail here:
Best Practice: Return mutableArray.copy or mutableArray if return type is NSArray

i was search for the answer in swift 3 and this question was showed as first result in search and i get inspired the answer from it
so here is the swift 3 code
let array: [String] = nsMutableArrayObject.copy() as! [String]

Related

componentsSeparatedByString - convert to array of NSMutableStrings [duplicate]

How to do that without having to "scroll" the entire given array with a "for" loop?
The best I can come up with is:
NSMutableArray *replacementArray = [NSMutableArray array];
[originalArray enumerateObjectsUsingBlock:
^(id obj, NSUInteger index, BOOL *stop)
{
[replacementArray addObject:[[obj mutableCopy] autorelease]];
}
];
Which more or less just tells the originalArray to construct the for loop for you. And if anything it's more work than:
NSMutableArray *replacementArray = [NSMutableArray array];
for(id obj in originalArray)
[replacementArray addObject:[[obj mutableCopy] autorelease]];
Since nobody seems to agree with my comment that this is a duplicate of Better way to convert NSArray of NSNumbers to array of NSStrings, here's the same answer again:
NSArray * arrayOfMutableStrings = [arrayOfStrings valueForKey:#"mutableCopy"];
From the docs:
valueForKey:
Returns an array containing the results of invoking
valueForKey: using key on each of the array's objects.
- (id)valueForKey:(NSString *)key
Parameters
key The key to retrieve.
Return Value
The value of the retrieved key.
Discussion
The returned array contains NSNull elements for each object that returns nil.
I wrote a dictionary method on NSArray to be able to write cleaner functional code
-(NSArray *)arrayByPerformingBlock:(id (^)(id))performBlock
{
NSMutableArray *array = [NSMutableArray array];
for (id element in self)
[array addObject:performBlock(element)];
return [NSArray arrayWithArray:array];
}
usage:
arrayWithStrings = [arrayWithStrings arrayByPerformingBlock:^id(id element) {return [[element mutableCopy] autorelease];}];
This was inspired by list comprehensions I know from Python. I also wrote versions of this methods with testing. See my arraytools.

Create a dynamic array

I am new. It's a basic question i guess.
Suppose I need to have a dynamic array to store several objects from my Own class,like classA. I ve no idea about how to wrap these classA-objects and put 'em into the array, maybe NSMutableArray. thx alot.
#interface classA
{
int x;
int y;
}
...
classA *a,*b,*c;
Initialize your array with :
NSMutableArray *myArray = [[NSMutableArray alloc] init];
And then add an object with :
[myArray addObject:a];
[myArray addObject:b];
And so on
You can find it all explained here : https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html
If you need your array to be mutable,
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:2];
[arr addObject:a];
[arr addObject:b];
will suffice. Objective-C, like Smalltalk, uses dynamic typing. You can just add the objects.
If you do not need to mutate your array,
NSArray *arr = #[a, b];

convert NSArray of NSString(s) to NSArray of NSMutableString(s)

How to do that without having to "scroll" the entire given array with a "for" loop?
The best I can come up with is:
NSMutableArray *replacementArray = [NSMutableArray array];
[originalArray enumerateObjectsUsingBlock:
^(id obj, NSUInteger index, BOOL *stop)
{
[replacementArray addObject:[[obj mutableCopy] autorelease]];
}
];
Which more or less just tells the originalArray to construct the for loop for you. And if anything it's more work than:
NSMutableArray *replacementArray = [NSMutableArray array];
for(id obj in originalArray)
[replacementArray addObject:[[obj mutableCopy] autorelease]];
Since nobody seems to agree with my comment that this is a duplicate of Better way to convert NSArray of NSNumbers to array of NSStrings, here's the same answer again:
NSArray * arrayOfMutableStrings = [arrayOfStrings valueForKey:#"mutableCopy"];
From the docs:
valueForKey:
Returns an array containing the results of invoking
valueForKey: using key on each of the array's objects.
- (id)valueForKey:(NSString *)key
Parameters
key The key to retrieve.
Return Value
The value of the retrieved key.
Discussion
The returned array contains NSNull elements for each object that returns nil.
I wrote a dictionary method on NSArray to be able to write cleaner functional code
-(NSArray *)arrayByPerformingBlock:(id (^)(id))performBlock
{
NSMutableArray *array = [NSMutableArray array];
for (id element in self)
[array addObject:performBlock(element)];
return [NSArray arrayWithArray:array];
}
usage:
arrayWithStrings = [arrayWithStrings arrayByPerformingBlock:^id(id element) {return [[element mutableCopy] autorelease];}];
This was inspired by list comprehensions I know from Python. I also wrote versions of this methods with testing. See my arraytools.

Add NSStrings to mutable array

I created a mutable array and I have two NSString variables. Now I want to add these two NSStrings to my array. How is this possible? Thanks.
Use the addObject function of you NSMutableArray.
eg.
[myNSMutableArray addObject:myString1];
[myNSMutableArray addObject:myString2];
Jhaliya's answer is correct. +1 vote.
I added a immutable version so you can see the difference. If you dont want to remove or add more objects (NSStrings) to your container, I would recommend using an Immutable version.
Mutable version:
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
NSString *string_one = #"One"];
[mutableArray addObject:string_one];
//Or
[mutableArray addObject:#"Two"];
NSLog(#"%#", mutableArray);
Immutable version
NSArray *immutableArray = [NSArray arrayWithObjects:#"One", #"Two", nil];
NSLog(#"%#", immutableArray);
You can add at NSMutableArray allocation.
Like :
NSMutableArray *test = [NSMutableArray arrayWithObjects:#"test1",#"test2",nil];

NSArray filled with bool

I am trying to create an NSArray of bool values. How many I do this please?
NSArray *array = [[NSArray alloc] init];
array[0] = YES;
this does not work for me.
Thanks
NSArrays are not c-arrays. You cant access the values of an NSArray with array[foo];
But you can use c type arrays inside objective-C without problems.
The Objective-C approach would be:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithBool:YES]];
//or
[array addObject:#(NO)];
...
BOOL b = [[array objectAtIndex:0] boolValue];
....
[array release];
EDIT: New versions of clang, the now standard compiler for objective-c, understand Object subscripting. When you use a new version of clang you will be able to use array[0] = #YES
Seems like you've confused c array with objc NSArray. NSArray is more like a list in Java, into which you can add objects, but not values like NSInteger, BOOL, double etc. If you wish to store such values in an NSArray, you first need to create a mutable array:
NSMutableArray* array = [[NSMutableArray alloc] init];
And then add proper object to it (in this case we'll use NSNumber to store your BOOL value):
[array addObject:[NSNumber numberWithBool:yourBoolValue]];
And that's pretty much it! If you wish to access the bool value, just call:
BOOL yourBoolValue = [[array objectAtIndex:0] boolValue];
Cheers,
Pawel
Use [NSNumber numberWithBool: YES] to get an object you can put in the collection.