Reputation: 33644
So I have a very weird issue in which that when I run my app on the simulator and the iPad plugged in (running the app on the device with cable plugged) it all works just fine. However after running on the device after it's plugged and I tried to use the app, it crashes.. tried looking at the device crash logs and I am seeing:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x3672bf78 objc_msgSend + 16
1 App 0x000ca834 -[AHAppImageData dealloc] (AHInstagramImageData.m:122)
2 libobjc.A.dylib 0x3672d16e _objc_rootRelease + 30
3 CoreFoundation 0x33d792e0 CFRelease + 88
4 CoreFoundation 0x33d8ea30 -[__NSArrayM removeObjectAtIndex:] + 288
5 CoreFoundation 0x33d84adc -[NSMutableArray removeAllObjects] + 64
6 App 0x000f717e -[AHImageDataSource clearDataSource] (AHImageDataSource.m:53)
7 App 0x000c0a36 __49-[AHMainViewController loadRequestWithURLString:]_block_invoke_0 (AHMainViewController.m:91)
8 libdispatch.dylib 0x32658c52 _dispatch_call_block_and_release + 6
9 libdispatch.dylib 0x3265aee0 _dispatch_main_queue_callback_4CF$VARIANT$mp + 188
10 CoreFoundation 0x33e032a6 __CFRunLoopRun + 1262
11 CoreFoundation 0x33d8649e CFRunLoopRunSpecific + 294
12 CoreFoundation 0x33d86366 CFRunLoopRunInMode + 98
13 GraphicsServices 0x37d68432 GSEventRunModal + 130
14 UIKit 0x36820cce UIApplicationMain + 1074
15 App 0x000b2860 main (main.m:16)
16 App 0x000b2820 0xb1000 + 6176
Any idea why this is only happening on device and not when running the app when plugged in or simulator?
Based on the comment below, I am showing the code that is responsible for this:
[[AHMyAppAPIClient sharedClient] getPath:requestURLPath parameters:nil
success:^(AFHTTPRequestOperation *operation, id response) {
[self.progressHUD_ hide:YES];
self.nextPaginationURL_ = [[response valueForKey:@"pagination"] valueForKey:@"next_url"];
[self.collectionView_.pullToRefreshView stopAnimating];
[[NSOperationQueue sharedOperationQueue] cancelAllOperations];
NSArray *arr = [response valueForKey:@"data"];
if ([arr count] > 0){
[[AHImageDataSource sharedDataSource] clearDataSource];
}
for (NSDictionary * data in arr){
AHInstagramImageData * imgData = [[AHInstagramImageData alloc] initWithData:data];
[[AHImageDataSource sharedDataSource] addObject:imgData];
[imgData release];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView_ setContentOffset:CGPointMake(0, 0)];
[self.collectionView_ reloadData];
});
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self.progressHUD_ hide:YES];
NSLog(@"Error fetching user data!");
NSLog(@"%@", error);
}];
This is how I am setting the data source:
extern NSString * const kClearDataSource;
@interface AHImageDataSource : NSObject
+ (AHImageDataSource *)sharedDataSource;
- (void) clearDataSource;
- (void) addObject:(id) object;
- (void) addObject:(id)object atIndex:(int) index;
- (int) count;
- (id) objectAtIndex:(int) index;
@end
NSString * const kClearDataSource = @"clearDataSource";
@interface AHImageDataSource()
{
NSMutableArray * imageDataSource_;
}
@property (nonatomic, retain) NSMutableArray * imageDataSource_;
@end
@implementation AHImageDataSource
@synthesize imageDataSource_;
+ (AHImageDataSource *)sharedDataSource {
static AHImageDataSource *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] init];
});
return _sharedClient;
}
- (id)init {
self = [super init];
if (!self) {
return nil;
}
NSMutableArray * temp = [[NSMutableArray alloc] initWithCapacity:200];
self.imageDataSource_ = temp;
[temp release];
return self;
}
-(void) clearDataSource
{
if ([self.imageDataSource_ count] > 0){
[self.imageDataSource_ removeAllObjects];
}
}
- (void) addObject:(id) object
{
[self.imageDataSource_ addObject:object];
}
- (void) addObject:(id)object atIndex:(int) index
{
[self.imageDataSource_ insertObject:object atIndex:index];
}
- (int) count
{
return [self.imageDataSource_ count];
}
- (id) objectAtIndex:(int) index
{
if (index >= 0 && index < [self.imageDataSource_ count]){
return [self.imageDataSource_ objectAtIndex:index];
}
return nil;
}
- (void) dealloc
{
[super dealloc];
[imageDataSource_ release];
}
@end
EDIT:
It seems that the NSZombieEnabled seemed to hide this issue. When I disable NSZombieEnabled it crashes now on the simulator and device.
Upvotes: 2
Views: 638
Reputation: 2958
I agree with Jim, looks like a double release.
I would utilize the Instruments 'zombie' profile to test for this situation. It can only be done in the simulator, but should show you exactly what is being double released.
Once that is 100% clear, it is typically pretty easy to resolve the situation.
Upvotes: 1
Reputation: 73936
It looks like you're over-releasing an instance of AHInstagramImageData
by putting it into a dictionary, then lowering the retain count enough for it to be deallocated. Then, when it's removed from the dictionary, it's released again and it tries to deallocate memory for an object that no longer exists.
Post the code responsible and you may get more detailed help. A crash log alone is not really enough to go on.
Upvotes: 0