Reputation: 14553
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:
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
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 becausethumbnailImage
is an ivar.UIImage imageWithCGImage
is 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 tothumbnailImage
directly, 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,release
it if there is one, then do aretain
on 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
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