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

时间:2011-05-11 21:32:43

标签: iphone objective-c cocoa-touch memory-management nsmutablearray

嘿伙计们,所以我在运行我的程序时遇到这些不一致的错误,只有大约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'

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'

我已经使用调试器运行它并且无法确定我的程序在哪个位置失败,但是,我确实有一个暗示它可能在我编写的这段新代码中(另外抛出)保留在这里和那里帮助这个错误 - 将处理稍后释放):

-(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

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

2 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:2)

所以调试消息非常自我解释:在某些时候,你试图在数组中插入一个不存在的对象。

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

我会建议你a)确定导致这些nil值出现的原因(可能是错误的输入数据),以及b)如果你无法让你的输入数据正常运行,那么防御性地编写你的app应用程序考虑到了。

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

if ([l lotname]) {
    [arrayOfALotTitles addObject:[[l lotName]retain]];
}

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