Problems Adding to NSMutableArray: attempt to insert nil object at 10
Hey guys, so I am getting these inconsistent errors when running my program, only about 50% of the time do these errors occur, and at seemingly different points of my program. Here is the console output:
2011-05-11 14:22:03.926 Parking[20611:1903] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSMutableArray insertObject:atIndex:]: attempt to insert nil object at 10'
*** Call stack at first throw:
(
0 CoreFoundation 0x011afbe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x013045c2 objc_exception_throw + 47
2 CoreFoundation 0x011a97f1 -[__NSArrayM insertObject:atIndex:] + 225
3 CoreFoundation 0x011a4c44 -[__NSArrayM addObject:] + 68
4 Parking 0x000182fd -[DataLoader loadOverlaysFromStore] + 1521
5 Parking 0x00017b76 -[DataLoader main] + 64
6 Foundation 0x00c5ebd2 -[__NSOperationInternal start] + 747
7 Foundation 0x00c5e826 ____startOperations_block_invoke_2 + 106
8 libSystem.B.dylib 0x9488c024 _dispatch_call_block_and_release + 16
9 libSystem.B.dylib 0x9487e2f2 _dispatch_worker_thread2 + 228
10 libSystem.B.dylib 0x9487dd81 _pthread_wqthread + 390
11 libSystem.B.dylib 0x9487dbc6 start_wqthread + 30
)
terminate called after throwing an instance of 'NSException'
And:
2011-05-11 14:16:45.171 Parking[20500:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSMutableArray insertObject:atIndex:]: attempt to insert nil object at 2'
*** Call stack at first throw:
(
0 CoreFoundation 0x011afbe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x013045c2 objc_exception_throw + 47
2 CoreFoundation 0x011a97f1 -[__NSArrayM insertObject:atIndex:] + 225
3 CoreFoundation 0x011a4c44 -[__NSArrayM addObject:] + 68
4 Parking 0x00012887 -[CoreDataSingleton getParkingLotTitlesForPermits:] + 1030
5 Parking 0x00004891 -[ParkingMapViewController sortLotsIntoSetsAccordingToPermitsAccepted] + 616
6 Parking 0x00006317 -[ParkingMapViewController viewDidLoad] + 1474
7 UIKit 0x000fc65e -[UIViewController view] + 179
8 UIKit 0x000faa57 -[UIViewController contentScrollView] + 42
9 UIKit 0x0010b201 -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] + 48
10 UIKit 0x00109831 -[UINavigationController _layoutViewController:] + 43
11 UIKit 0x0010ab4c -[UINavigationController _startTransition:fromViewController:toViewController:] + 524
12 UIKit 0x00105606 -[UINavigationController _startDeferredTransitionIfNeeded] + 266
13 UIKit 0x0021de01 -[UILayoutContainerView layoutSubviews] + 226
14 QuartzCore 0x01a15451 -[CALayer layoutSublayers] + 181
15 QuartzCore 0x01a1517c CALayerLayoutIfNeeded + 220
16 QuartzCore 0x01a15088 -[CALayer layoutIfNeeded] + 111
17 UIKit 0x000fdb5f -[UIViewController window:willAnimateRotationToInterfaceOrientation:duration:] + 587
18 UIKit 0x000768e9 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 4347
19 UIKit 0x002f5948 -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] + 1053
20 UIKit 0x00100982 -[UIViewController presentModalViewController:withTransition:] + 3151
21 Parking 0x0000b104 -[SampleHomeScreen appButtonTapped:] + 124
22 UIKit 0x0004ea6e -[UIApplication sendAction:to:from:forEvent:] + 119
23 UIKit 0x000dd1b5 -[UIControl sendAction:to:forEvent:] + 67
24 UIKit 0x000df647 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
25 UIKit 0x000de1f4 -[UIControl touchesEnded:withEvent:] + 458
26 UIKit 0x000730d1 -[UIWindow _sendTouchesForEvent:] + 567
27 UIKit 0x0005437a -[UIApplication sendEvent:] + 447
28 UIKit 0x00059732 _UIApplicationHandleEvent + 7576
29 GraphicsServices 0x01424a36 PurpleEventCallback + 1550
30 CoreFoundation 0x01191064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
31 CoreFoundation 0x010f16f7 __CFRunLoopDoSource1 + 215
32 CoreFoundation 0x010ee983 __CFRunLoopRun + 979
33 CoreFoundation 0x010ee240 CFRunLoopRunSpecific + 208
34 CoreFoundation 0x010ee161 CFRunLoopRunInMode + 97
35 GraphicsServices 0x01423268 GSEventRunModal + 217
36 GraphicsServices 0x0142332d GSEventRun + 115
37 UIKit 0x0005d42e UIApplicationMain + 1160
38 Parking 0x00002424 main + 102
39 Parking 0x000023b5 start + 53
)
terminate called after throwing an instance of 'NSException'
I have run through it with a debugger and have not been able to determine at which point of my program it fails at, however, I do have an inkling it may be within this new section of code I wrote (tossed in additional retains here and there to help this error-will deal with releasing later):
-(id)initWithFunction:(LoaderFunc)func withDelegate:(id)delegate setRestricted:(NSSet *)restricted
setA:(NSSet *)A setC:(NSSet *)C setL:(NSSet *)L {
if (self = [super init]) {
self.addedOverlays = [[NSMutableArray alloc] init];
self.addedAnnotations = [[NSMutableArray alloc] init];
self.overlayRegions = [[NSMutableArray alloc] init];
self.loaderFunc = func;
self.DLDelegate = delegate;
return self;
}
return nil;
}
//...
-(void)loadOverlaysFromStore {
NSLog(@"DataLoader.m loadOverlaysFromStore");
//NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary *permits;
permits = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"0",@"0",@"0",nil] forKeys:[NSArray arrayWithObjects:@"A",@"C",@"L",nil]];
NSSet *setOfRestrictedLots = [[NSSet setWithArray:[[CoreDataSingleton sharedManager] getParkingLotsForPermits:permits]] retain];
NSMutableArray *arrayOfRestrictedLotTitles = [[NSMutableArray alloc] init];
for (ParkingLot *l in [setOfRestrictedLots allObjects]) {
[arrayOfRestrictedLotTitles addObject:[[l lotName]retain]];
}
permits = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1",@"0",@"0",nil] forKeys:[NSArray arrayWithObjects:@"A",@"C",@"L",nil]];
NSSet *setOfALots = [[NSSet setWithArray:[[CoreDataSingleton sharedManager] getParkingLotsForPermits:permits]] retain];
NSMutableArray *arrayOfALotTitles = [[NSMutableArray alloc] init];
for (ParkingLot *l in [setOfALots allObjects]) {
[arrayOfALotTitles addObject:[[l lotName]retain]];
}
permits = [NSDictionary dictionaryWithObjects:[NSArray arrayWith开发者_开发知识库Objects:@"1",@"1",@"0",nil] forKeys:[NSArray arrayWithObjects:@"A",@"C",@"L",nil]];
NSSet *setOfCLots = [[NSSet setWithArray:[[CoreDataSingleton sharedManager] getParkingLotsForPermits:permits]] retain];
NSMutableArray *arrayOfCLotTitles = [[NSMutableArray alloc] init];
for (ParkingLot *l in [setOfCLots allObjects]) {
[arrayOfCLotTitles addObject:[[l lotName]retain]];
}
permits = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1",@"1",@"1",nil] forKeys:[NSArray arrayWithObjects:@"A",@"C",@"L",nil]];
NSSet *setOfLLots = [[NSSet setWithArray:[[CoreDataSingleton sharedManager] getParkingLotsForPermits:permits]] retain];
NSMutableArray *arrayOfLLotTitles = [[NSMutableArray alloc] init];
for (ParkingLot *l in [setOfLLots allObjects]) {
[arrayOfLLotTitles addObject:[[l lotName]retain]];
}
[addedOverlays addObject:setOfRestrictedLots];
[addedOverlays addObject:setOfALots];
[addedOverlays addObject:setOfCLots];
[addedOverlays addObject:setOfLLots];
for (NSSet* set in addedOverlays) {
for (ParkingLot *lot in [set allObjects]) {
ParkingRegionOverlay *regionPolygon = [[ParkingRegionOverlay alloc] initWithPoints:[lot overlayCoordPoints]
andTitle:[lot lotName]
setRestricted:[NSSet setWithArray:arrayOfRestrictedLotTitles]
setA:[NSSet setWithArray:arrayOfALotTitles]
setC:[NSSet setWithArray:arrayOfCLotTitles]
setL:[NSSet setWithArray:arrayOfLLotTitles]];
[overlayRegions addObject:regionPolygon];
[regionPolygon release];
}
}
}//loadOverlays
Any help greatly appreciated. Thanks!
So I figured it out. Remember how I said it occurred only about 50% of the time? That was a HUGE hint by the way as I had some code that retrieved data from my Core Data Store that was accessed in two ways. I had modified my code to have a background thread access that method but forgot to remove the call to it from a portion of the code where the main thread operates. Thus there would be race conditions in accessing the data, and I am not too sure why it would result in obtaining a nil value in some cases, but removing the call to that function from the main thread rectified the problem.
So the debug message is pretty self explanatory: at some point, you're trying to insert an object that doesn't exist into your array.
Since based on the logs you posted it seems to be happening in several places in your application the best strategy is to ensure it's impossible to insert a nil value into your arrays in the first place.
I would recommend you either a) establish what's causing these nil values to come up (presumably bad input data), and b) if you're unable to get your input data to behave correctly, defensively code your app to take that into account.
To be honest, it's probably a good idea to check you're not trying to insert a nil value object anyway. You could either use a try/catch statement to catch the exception when it happens, or test the object before you inserted it:
if ([l lotname]) {
[arrayOfALotTitles addObject:[[l lotName]retain]];
}
(PS: not sure why you're explicitly retaining when you add to an array. Normally you wouldn't need to do this. Hope you're matching it back with a corresponding release call!).
精彩评论