What are the differences between [[NSMutableArray alloc] init] and [#[] mutableCopy]? - objective-c

NSMutableArray *myArray = [[NSMutableArray alloc] init];
vs
NSMutableArray *myArray = [#[] mutableCopy]
What are the differences between declaring arrays in these two separate ways?

Think of the 2nd line as:
NSMutableArray *myArray = [[[NSArray alloc] init] mutableCopy];
So the clear difference is the 1st way is more efficient and the 2nd way needlessly creates an extra object that is promptly discarded.

Related

memory menagement in ios

Can anybody explain me why does the case1 and case2 crashes while the others does not in case of non-ARC?
Case1:
NSString *rr = [[NSString alloc] initWithString:#"AB"];
[rr release];
[rr autorelease];
Case2:
NSString *rrr = [[NSString alloc] initWithString:#"AB"];
[rrr autorelease];
[rrr release];
Case3:
NSMutableString *rr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rr1 release];
[rr1 autorelease];
Case4:
NSMutableString *rrr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rrr1 autorelease];
[rrr1 release];
Case5:
NSArray *rr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rr3 release];
[rr3 autorelease];
Case6:
NSArray *rrr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rrr3 autorelease];
[rrr3 release];
Case7:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 release];
[rr2 autorelease];
Case8:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 autorelease];
[rr2 release];
All are are incorrect because eventually all will be released twice, but some may coincidentally not crash.
The alloc allocates the object with a retain count of 1. release decreases the retain count 1. autorelease eventually decreases the retain count 1. That means that all are over released.
But as #Chuck mentions some instances are constants, are created at compile time and never released so release and autorelease can be called to many tines with no crash.
String constants are one instance of this this where over-releasing will not cause a crash:
NSString *s = #"aa";
Even over-releasing this is OK because the compiler is smart enough:
NSString *s = [NSString stringWithString:#"aa"];
But you will get a warning from the current LLVM compiler that using stringWithString with a literal is redundant.

What is the different between NSArray Parsing?

What is the difference between of Parsing in the following code segments.
which codes segments is faster in Parsing?
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = (NSMutableArray *)arr;
(and)
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = [NSMutableArray arrayWithArray:arr];
You have the same mistake in both snippets, you allocate memory for the object, and then assign something else to data, which makes you lose the previous (and have memory leak), e.g. this:
NSMutableArray *data = [[NSMutableArray alloc] init];
data = [NSMutableArray arrayWithArray:arr];
should be
NSMutableArray *data = [NSMutableArray arrayWithArray:arr];
Now for the question itself:
The first case is a bad idea, you cast the NSArray, but you canot modify it, as you didn't really changed its type, only assigned it to NSMutaleArray pointer.
The second case will create a new NSMutableArray which is mutable, with the contents of the NSArray, and this is cool, you may alter this array now.
It looks like what you want is either:
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = [arr mutableCopy];
or:
NSMutableArray *data = [[NSMutableArray alloc] initWithObjects:#"Apple",#"Macbook", nil];

Sort NSMutableArray memory leak

My object has a private NSMutableArray items. I am using the following code to sort the objects in items in size order:
-(void)sortItems{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"size" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray = [items sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray* newArray = [[NSMutableArray alloc] initWithArray: sortedArray];
[self setItems:newArray];
[sortDescriptor release];
}
Obviously this is a memory leak here, because every time I call sortItems, I am allocing new memory and assigning items to point to it. I've tried releasing the old memory as follows:
NSMutableArray* newArray = [[NSMutableArray alloc] initWithArray: sortedArray];
NSMutableArray* oldArray = [self items];
[self setItems:newArray];
[oldArray release];
But that gives an EXC_BAD_ACCESS error. I've read up on memory handling in objC, and I'm convinced I'm doing something fundamentally wrong here.
Any help would be greatly appreciated!
You're leaking the new array, not the old one:
NSMutableArray* newArray = [[NSMutableArray alloc] initWithArray: sortedArray];
[self setItems:newArray];
[sortDescriptor release];
[newArray release]; // <-- add this
The fundamental rule is that you must release anything that you have allocated, and you normally shouldn't care about keeping things retained for anyone (i.e. [self setItems:]), those who need something retained will do it themselves.
I would also recommend making self.items a mutable array, and using [self.items sortUsingDescriptors:sortDescriptor to sort inplace without creating a copy.
Is there a reason why you cannot release the newArray in your first example?
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"size" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray = [items sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray* newArray = [[NSMutableArray alloc] initWithArray: sortedArray];
[self setItems:newArray];
[newArray release];
[sortDescriptor release];

Difference in NSMutableArray declaration

What is the difference between [NSMutableArray array] and [[NSMutableArray alloc] init]?
[NSMutableArray array] is equivalent to [[[NSMutableArray alloc] init] autorelease].
[NSMutableArray array]
returns an autoreleased array.
[[NSMutableArray alloc] init]
returns a retained array.
You don't own the autoreleased array, so you don't have to release it. You own the retained one (with alloc), so you have to release it.

How to copy last object of array to other array?

how would you copy the last object of a array and then add the object to some array. So in other words i want to take the last object of someArray and copy that lastObject to someArray2.
Thanks,
-David
NSArray *firstArray = [[NSArray alloc] init];
... populate firstArray ...
NSArray *secondArray = [NSArray arrayWithObject:[firstArray lastObject]];
or
NSArray *firstArray = [[NSArray alloc] init];
... populate firstArray ...
NSMutableArray *secondArray = [NSMutableArray alloc] init];
[secondArray addObject:[firstArray lastObject]];
or
NSArray *firstArray = [[NSArray alloc] init];
... populate firstArray ...
NSArray *secondArray = [[NSArray alloc] init];
NSArray *thirdArray = [secondArray arrayByAddingObject:[firstArray lastObject]];
Make sure everything is released as you now own all these references.
Edit: If you want a COPY everywhere there's [firstArray lastObject] change it to [[[firstArray lastObject] copy] autorelease] (thanks tc)