Can't add objects to a NSMutableArray - objective-c

So I have the following code:
NSMutableArray *array
array=[[NSMutableArray alloc] init];
[array addObject: object1];
[array addObject: object2];
NSLog(#"%#",array);
When I use the app in my iPod connected to my Mac, NSLog writes just null, I don't get object1 object2. What am I doing wrong?
PS: array is a property in .h #property (nonatomic, retain) NSMutableArray *array;

Should it be:
array=[[NSMutableArray alloc] init];

Your [[NSMutableArray array] init] should be [[NSMutableArray alloc] init]. That would work but its not a proper way to initialize objects. You didn't post what your array is, i assume you declared it wrong. It should be a pointer to a NSMutableArray object. Here is a working code:
NSMutableArray *array=[[NSMutableArray alloc] init];
[array addObject: #"a"];
[array addObject: #"b"];
NSLog(#"%#",array);

You are not initializing your array at all, that's why it doesn't return anything.
array=[[NSMutableArray alloc] init];
[array addObject: object1];
[array addObject: object2];
NSLog(#" Array is:%#",array);
Remember to release it afterwards(unless you are using ARC)

You could try doing it in one line.
NSMutableArray *array = [[NSMutableArray alloc] arrayWithObjects:#"a", #"b", nil];
NSLog(#"%#",array);

You declared array as a property. Its corresponding iVar gets initialized to nil.
So in your init method you have to initialize it:
Assuming you used
#synthesize array;
In your init method
if (self) {
//other init stuff
array = [[NSMutableArray array] retain];
}
Then when adding stuff
[self.array addObject: object];
Also note that he objects you put in there have to be properly initialized and r not nil.
So try to log this too
NSLog("the object %# was put in array. Array contains: %#",object, self.array);
And in dealloc, release your array!

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.

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.

memory leak and instance variables

-(void) getAccounts {
self.selAccounts = [[NSMutableArray alloc] init];
self.accounts = [[NSMutableArray alloc] init];
NSString *url=[NSString stringWithFormat:#"https://localhost//listaccts"];
self.processor=[[AsynConnectionProcessorController alloc] init];
self.processor.delegate=self;
self.processor.server=self.server;
[processor createRequestfromURL:url];
}
This method is causing memory leak when invoked. Now if I replace this with below
-(void) getAccounts {
[accounts release];
self.selAccounts = [[NSMutableArray alloc] init];
accounts = [[NSMutableArray alloc] init];
NSString *url=[NSString stringWithFormat:#"https://localhost//listaccts"];
self.processor=[[AsynConnectionProcessorController alloc] init];
self.processor.delegate=self;
self.processor.server=self.server;
[processor createRequestfromURL:url];
}
I am getting memory leak if I invoke this method second time as a result of viewcontroller beong popped from stack.
Why does this leak? accounts is an insyance variable with declration like this :
#property (nonatomic, retain) NSMutableArray *accounts;
Can't I assume that there won't be memory leak if I use setter via self.accounts?
This is wrong
self.accounts = [[NSMutableArray alloc] init];
the setter already does a retain, since you specified that in the property
#property (nonatomic, retain) NSMutableArray *accounts;
you should rewrite it like this
NSMutableArray arr = [[NSMutableArray alloc] init];
self.accounts = arr;
[arr release];
or alternatively:
self.accounts = [[[NSMutableArray alloc] init] autorelease];
EDIT: removed 'non preferred' - was subjective.

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)