添加到NSMutableArray的问题:尝试在10处插入nil对象

时间:2022-09-25 18:44:02

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:

嘿伙计们,所以我在运行我的程序时遇到这些不一致的错误,只有大约50%的时间会发生这些错误,并且在我的程序中看似不同的点。这是控制台输出:

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 arrayWithObjects:@"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!

任何帮助非常感谢。谢谢!

2 个解决方案

#1


4  

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.

所以我明白了。还记得我说它只发生了50%的时间吗?这是一个巨大的提示,因为我有一些代码可以从我的Core Data Store中检索以两种方式访问​​的数据。我修改了我的代码,让后台线程访问该方法,但忘记从主线程操作的代码的一部分中删除对它的调用。因此在访问数据时会出现竞争条件,我不太清楚为什么在某些情况下会导致获得nil值,但是从主线程中删除对该函数的调用可以解决问题。

#2


2  

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.

因为基于您发布的日志,它似乎发生在应用程序的几个地方,所以最好的策略是确保首先不可能将nil值插入到数组中。

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.

我会建议你a)确定导致这些nil值出现的原因(可能是错误的输入数据),以及b)如果你无法让你的输入数据表现正常,那么就可以对你的应用进行防御性编码以将其考虑在内。

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:

说实话,检查你是不是试图插入一个零值对象可能是个好主意。您可以使用try / catch语句在异常发生时捕获异常,也可以在插入之前测试该对象:

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!).

(PS:不确定为什么在添加到数组时明确保留。通常你不需要这样做。希望你将它与相应的释放调用匹配!)。

#1


4  

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.

所以我明白了。还记得我说它只发生了50%的时间吗?这是一个巨大的提示,因为我有一些代码可以从我的Core Data Store中检索以两种方式访问​​的数据。我修改了我的代码,让后台线程访问该方法,但忘记从主线程操作的代码的一部分中删除对它的调用。因此在访问数据时会出现竞争条件,我不太清楚为什么在某些情况下会导致获得nil值,但是从主线程中删除对该函数的调用可以解决问题。

#2


2  

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.

因为基于您发布的日志,它似乎发生在应用程序的几个地方,所以最好的策略是确保首先不可能将nil值插入到数组中。

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.

我会建议你a)确定导致这些nil值出现的原因(可能是错误的输入数据),以及b)如果你无法让你的输入数据表现正常,那么就可以对你的应用进行防御性编码以将其考虑在内。

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:

说实话,检查你是不是试图插入一个零值对象可能是个好主意。您可以使用try / catch语句在异常发生时捕获异常,也可以在插入之前测试该对象:

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!).

(PS:不确定为什么在添加到数组时明确保留。通常你不需要这样做。希望你将它与相应的释放调用匹配!)。