Проблемы с добавлением в NSMutableArray: попытка вставить нулевой объект в 10 - PullRequest
1 голос
/ 12 мая 2011

Привет, ребята, поэтому я получаю эти противоречивые ошибки при запуске моей программы, только примерно в 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 ]

4 голосов
/ 16 мая 2011

Так что я понял это.Помните, как я говорил, это происходило только в 50% случаев?Кстати, это был ОГРОМНЫЙ намек, поскольку у меня был некоторый код, который извлекал данные из моего основного хранилища данных, доступ к которому осуществлялся двумя способами.Я изменил свой код, чтобы фоновый поток обращался к этому методу, но забыл удалить вызов к нему из части кода, где работает основной поток.Таким образом, при доступе к данным могут возникать расы, и я не слишком уверен, почему в некоторых случаях это приведет к получению значения nil, но удаление вызова этой функции из основного потока решило проблему.

2 голосов
/ 12 мая 2011

Таким образом, сообщение отладки самоочевидно: в какой-то момент вы пытаетесь вставить объект, который не существует, в ваш массив.

Поскольку, судя по опубликованным вами журналам, кажется, что это происходит в нескольких местах вашего приложения, лучшая стратегия состоит в том, чтобы обеспечить невозможность вставки нулевого значения в ваши массивы.

Я бы порекомендовал вам либо: а) установить, что вызывает появление этих нулевых значений (предположительно, неверные входные данные), и б) если вы не можете заставить свои входные данные вести себя правильно, защитно кодируйте свое приложение, чтобы принять это во внимание.

Честно говоря, это, вероятно, хорошая идея проверить, что вы все равно не пытаетесь вставить объект с нулевым значением.Вы можете использовать оператор try / catch для перехвата исключения, когда оно происходит, или протестировать объект перед его вставкой:

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

(PS: не уверен, почему вы явно сохраняете его при добавлении вмассив. Обычно вам не нужно этого делать. Надеюсь, вы сопоставляете его с соответствующим вызовом релиза!).

...