I'm scratching my head over a memory leak with an instance variable NSArray which I'm filling with the contents of a temporary (and then released) NSMutableArray. The contents are UIButtons, which I'm releasing when I'm finished with them in a separate method. The leaking code seems to be below according to Instruments, leaking 208 bytes each time 'createButtons' is called again (it creates a grid of UIButtons 8x8):
Code:
-(void)createButtons {
for (int i=0; i<8; i++) {
for (int j=0; j<8; j++) {
UIButton *but = [UIButton buttonWithType:UIButtonTypeCustom];
but.frame = CGRectMake(i*60, j*60, 60, 60);
[but setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[but setTitle:@"text" forState:UIControlStateNormal];
[self.view addSubview:but];
[but addTarget:self action:@selector(pressLetter:) forControlEvents:UIControlEventTouchUpInside];
[tempTiles insertObject:but atIndex:(i*8)+j];
}
}
// tiles is declared as an instance variable of class
tiles = [[NSArray alloc] initWithArray:tempTiles]; // INSTRUMENTS POINTS TO THIS LINE FOR LEAK
[tempTiles release];
}
// method called later to remove buttons from screen for next grid
-(void)removeButtons {
if (tiles!=nil) {
for (int i=0; i<[tiles count]; i++) {
UIButton *but = [tiles objectAtIndex:i];
[but removeFromSuperview];
[but release];
}
tiles = nil;
}
}
Hope someone can shed some light on this - thanks!
I'm scratching my head over a memory leak with an instance variable NSArray which I'm filling with the contents of a temporary (and then released) NSMutableArray. The contents are UIButtons, which I'm releasing when I'm finished with them in a separate method. The leaking code seems to be below according to Instruments, leaking 208 bytes each time 'createButtons' is called again (it creates a grid of UIButtons 8x8):
Code:
-(void)createButtons {
for (int i=0; i<8; i++) {
for (int j=0; j<8; j++) {
UIButton *but = [UIButton buttonWithType:UIButtonTypeCustom];
but.frame = CGRectMake(i*60, j*60, 60, 60);
[but setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[but setTitle:@"text" forState:UIControlStateNormal];
[self.view addSubview:but];
[but addTarget:self action:@selector(pressLetter:) forControlEvents:UIControlEventTouchUpInside];
[tempTiles insertObject:but atIndex:(i*8)+j];
}
}
// tiles is declared as an instance variable of class
tiles = [[NSArray alloc] initWithArray:tempTiles]; // INSTRUMENTS POINTS TO THIS LINE FOR LEAK
[tempTiles release];
}
// method called later to remove buttons from screen for next grid
-(void)removeButtons {
if (tiles!=nil) {
for (int i=0; i<[tiles count]; i++) {
UIButton *but = [tiles objectAtIndex:i];
[but removeFromSuperview];
[but release];
}
tiles = nil;
}
}
Hope someone can shed some light on this - thanks!
It looks to me like you create the tiles array using initWithArray. That means you need to release tiles when you are done with it. In your removeButtons method, you set tiles to nil without releasing it. That looks like your leak right there. Just add a [tiles release] before setting tiles to nil in removeButtons, and it should solve your problem.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
It looks to me like you create the tiles array using initWithArray. That means you need to release tiles when you are done with it. In your removeButtons method, you set tiles to nil without releasing it. That looks like your leak right there. Just add a [tiles release] before setting tiles to nil in removeButtons, and it should solve your problem.
Thanks guys, really appreciated.
The leak is fixed now - adding the release as Duncan said did the trick. At first it was crashing, but I realised that I was also running a loop right before it to release all the button objects in the array before releasing it - not necessary as releasing the array sent a release to all those objects automatically anyway.