Ser Pounce
Ser Pounce

Reputation: 14553

Memory after recreated NSMutableArray reinitialized

I have a class that mimics the behavior of the UIImagePickerController except with some subtle differences. In my class, I use only one view controller and use it to swap out the albums tableview and photos tableview when the user makes a row / thumbnail selection. So the sequence of events that is causing me problems is as follows:

  1. I select an album
  2. The photos tableview loads, and I push the back button to go back to the albums tableview
  3. The albums tableview loads
  4. I select an album, and now a memory access error triggers

I have implemented both of the tableviews and the array in ivars as follows:

@property (nonatomic, retain) UITableView *selectAnAlbumTableView, *selectAPhotoTableView;
@property (nonatomic, retain) NSMutableArray *albums, *photos;
@property (nonatomic, retain) ALAssetsGroup *album;
@property (nonatomic, retain) UIActivityIndicatorView *spinner;

One difference between the albums tableview and the photos tableview is that the photos tableview is recreated each time a user selects an album and this is where the error occurs. Initially, the "EXC_BAD_ACCESS" was occurring when I was removing the tableview, like I do here:

        [[self selectAPhotoTableView] removeFromSuperview];
        [selectAPhotoTableView release];
        selectAPhotoTableView = nil;
        [photos release];
         photos = nil;

I noticed the error is occurring at [photos release]. Photos is the array where I store all of the thumbnail buttons that are put in cells on the photos tableview. If I remove [photos release] and photos = nil, then the problem occurs when the tableview is actually created (as I mentioned initially):

NSMutableArray *photosTemp = [[NSMutableArray alloc] init];
[self setPhotos: photosTemp];
[photosTemp release];

Now the "EXC_BAD_ACCESS" is being thrown after the [self setPhotos: photosTemp]; line. Does anyone know what I'm doing wrong here?

UPDATE: I put the wrong code for where the error occurs the second time, now it's fixed.

Upvotes: 0

Views: 121

Answers (2)

Max MacLeod
Max MacLeod

Reputation: 26652

I'll put this in an answer rather than a massive comment.

This line (see comments) will cause a problem:

thumbnailImage = [UIImage imageWithCGImage:[theALAsset thumbnail]]; 

That's becausethumbnailImageis an ivar.UIImage imageWithCGImageis returning you an autoreleased object. Therefore you must retain it either explicitly, as follows:

thumbnailImage = [[UIImage imageWithCGImage:[theALAsset thumbnail]] retain]; 

Or, you can let your property do it for you via the generated setters. Setting up a property as follows won't do anything because in your line above you are referring tothumbnailImagedirectly, not via the setters.

@property (nonatomic, retain) UIImage *thumbnailImage;

What you need to do is useself, so you have:

self.thumbnailImage = [UIImage imageWithCGImage:[theALAsset thumbnail]]; 

That will go through generated setters that first checking for any existing object,releaseit if there is one, then do aretainon your newly assigned object. All that happens automatically. In other words, it saves you the bother of doing:

-(void)setThumbnailImage:(UIImage *)aThumbnailImage
{
    [aThumbnailImage retain];
    if (thumbnailImage)
    {
        [thumbnailImage release];
    }
    thumbnailImage = aThumbnailImage;
}

Aaron Hillegass' book has a great explanation of this stuff in "Cocoa Programming for Mac OS X".

A key thing to do is to run builds with the Analyzer, or just run the Analyzer from time to time. It will spot a lot of these issues before you get to the time consuming process of tracking down EXC_BAD_ACCESS errors.

Upvotes: 1

Hot Licks
Hot Licks

Reputation: 47729

EXC_BAD_ACCESS means that you presented a pointer that isn't valid (and in this context nil can be considered "valid"). In your first case that bad pointer would appear to be photos.

If it were an auto variable it could be bad because you failed to initialize it, but the system always nulls instance variables.

So either you assigned something invalid to it, or the value that was in it is still there, but the object it addressed has been released.

The error in the second case is oddly suggesting that "self" has been released. This could well be your root problem, and your dealloc method is releasing photos, so that shows the error first. I'd suggest you place a NSLog in your dealloc routine to see if it's getting invoked too soon, and, if so, then obviously figure out how you failed to properly retain your controller object.

Upvotes: 0

Related Questions