What is the difference between
NSMutableArray* p = [[NSMutableArray alloc] initWithObjects:...]
and
NSMutableArray* p = [NSMutableArray arrayWithObjects:...]
In the first one, you have the ownership of array object & you have to release them.
NSMutableArray* p = [[NSMutableArray alloc] initWithObjects:...];
[p release];
& last one you dont need to release as you don't have the ownership of array object.
NSMutableArray* p = [NSMutableArray arrayWithObjects:...]; //this is autoreleased
If you call release in this, then it will crash your application.
[NSMutableArray arrayWithObjects:] is the same as [[[NSMutableArray alloc] initWithObjects:] autorelease]
In practice, there is no difference if you're on ARC.
The latter basically is just a shorthand for [[NSMutableArray alloc] initWithObjects: ...], except the returned array is autoreleased (which is important if you're still doing manual reference counting).
What I think the difference is that: initWithObjects is a instance method, and arrayWithObject is a class method.
Related
There seem to be different methods of instantiating NSArrays (same for NSDictionary and some others).
I know:
[NSArray array]
[NSArray new]
#[]
[[NSArray alloc] init]
For readability reasons I usually stick with [NSArray array], but what is the difference between all those, do they all really do the same?
Results are same for all of them, you get a new empty immutable array. These methods have different memory management implications though. ARC makes no difference in the end, but before ARC you would have to use the right version or send appropriate retain, release or autorelease messages.
[NSArray new], [[NSArray alloc] init] return an array with retain count is 1. Before ARC you would have to release or autorelease that array or you'd leak memory.
[NSArray array], #[] return an already autoreleased array (retain count is 0). If you want it to stick around without ARC you'd have to manually retain it or it would be deallocated when the current autorelease pool gets popped.
[NSArray array] : Create and return an empty array
[NSArray new] : alloc, init and return a NSArray object
#[] : Same as 1.
[[NSArray alloc] init] : Same as 2.
Different between [NSArray array] and [[NSArray alloc] init] is if there are non-ARC:
[NSArray array] is an autorelease object. You have to call retain if you want to keep it. E.g when you return an array.
[[NSArray alloc] init] is an retained object. So you don't have to call retain more if you want keep it.
With ARC, they are same.
I've gone crazy trying to find a leak with an NSMutableArray:
NSMutableArray *mutablearray =[[[[NSMutableArray alloc] initWithArray: array] mutableCopy] autorelease];
Finally I understood that I need to autorelease twice my mutablearray because initWithArray is +1 and mutableCopy is +1 too.
Then I'm doing:
NSMutableArray *mutablearray = [[[NSMutableArray alloc] initWithArray: array] autorelease];
mutablearray = [[mutablearray mutableCopy] autorelease];
But, it's correct to do?:
NSMutableArray *mutablearray = [[[[[NSMutableArray alloc] initWithArray: array] autorelease] mutableCopy] autorelease];
Thanks
The first question comes in mind is WHY you are initializing and also making a mutable copy at the same time initWithArray gives a new instance with new memory and you can use it.Then why creating a mutable copy of it?
Use
NSMutableArray *mutablearray = [[[NSMutableArray alloc] initWithArray: array]autorelease];
This gives you a mutable instance .So no need for calling mutablecopy anyway
OR
NSMutableArray *mutablearray = [[array mutableCopy]autorelease];
arrayOfElements = [NSMutableArray arrayWithArray:[someObj getArray]];
and
arrayOfElements = [[NSMutableArray alloc] init];
arrayOfElements = [someObj getArray];
What's the difference?
The first arrayOfElements does not seem to lose its objects when it returns count in numberOfRowsInSection:(NSInteger)section, but the second one does. I get EXC_BAD_ACCESS when I do it the second way.
EDIT:
Can I suppose now that this is the best way,
arrayOfElements = [[NSMutableArray alloc] initWithArray:[someObj getArray]];
because I am initializing an array with the contents of whatever will be autorelease'd, and I now have a fully independent array in the current class, that is viewDidLoad, oops sorry, ViewController.
This line creates an NSMutableArray from an existing array
arrayOfElements = [NSMutableArray arrayWithArray:[someObj getArray]];
This combination first creates an NSMutableArray and then instantly discards it replacing it with what is returned by [someObj getArray]
arrayOfElements = [[NSMutableArray alloc] init]; // Create new NSMutableArray
arrayOfElements = [someObj getArray]; // Throw away the newly created array and replace with the result of [someObj getArray]
If you are not using ARC then it is purely by luck that either would work.
In both cases arrayOfElements is being assigned an autorelease'd object - which will be cleared soon (most likely the next runloop). It is only by chance that nothing else has been written over this point of memory which allows one of your implementations to still work.
If you are not using ARC then really you should update your project to be using it will handle a lot of cases like this for you.
You should definitely be using properties (not bare ivars) as this will help reduce memory issues (for non-ARC) and give a more consistent interface to your code.
In your header (or class extension) declare the property like this
#property (nonatomic, strong) NSMutableArray *arrayOfElements;
Now for ARC you can simple do
[self setArrayOfElements:[[someObj getArray] mutableCopy];
for non-ARC you can do
NSMutableArray *array = [[someObj getArray] mutableCopy];
[self setArrayOfElements:array];
[array release]; array = nil;
Also note that getArray is a bad method name.
The use of “get” is unnecessary, unless one or more values are returned indirectly.
Coding Guidelines
When you are adding objects to mutable array from another array, try this:
[arrayOfElements addObjectsFromArray: [someObj getArray]];
If you're not using ARC, you need to make sure its retained.
if (arrayOfElements) {
[arrayOfElements release];
}
arrayOfElements = [[NSMutableArray alloc] initWithArray:[someObj getArray]];
I am from android background and I just started working on iPhone
I want to perform this operation in iPhone as I do in Android.
ArrayList<String> aa = new ArrayList<String>();
public void fillArray(String s)
{
aa.add(s);
}
As Binyamin Sharet suggest you have to use NSMutableArray. This class allows you to create a dynamic array. You can perform addition or deletion. On the contrary NSArray is a immutable version of it. You cannot add or delete objects to a NSArray once created.
The same distinction can be applied to NSDictionary and NSMutableDictionary (and other).
Here a simple example.
NSMutableArray* arr = [[NSMutableArray alloc] init];
[arr addObject:#"first string"];
[arr addObject:#"second string"];
An important aspect of NSMutableArray (the same could be applied to other class) is the memory management one. When you add an object to a NSMutableArray it retains objects added to it. So, if you NOT use ARC you have to deal with this aspect.
NSMutableArray* arr = [[NSMutableArray alloc] init];
id obj = [[NSObject alloc] init]; // a general object
[arr addObject:obj];
[obj release];
For further info I suggest you to read about NSMutableArray class reference.
Hope it helps.
This is very basic but I don't know how to do it.
How can a NSMutableArray object be cleared from all elements. I want to set the array to the state when it was created:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
Thanks
[myArray removeAllObjects];
Docs can be found here