2013-04-26 48 views
1

我有一個UITableView,它是從一個XML數據源解析的數據數組中填充的。我努力尋找這個錯誤的原因,並想知道是否有人可以幫助我。錯誤不會經常發生。它只發生在數組數很大時,例如10-15個對象,然後一旦刷新,他們的數組就是一個較小的數字,比如3-4個對象。通常這個錯誤是在這一行上引發的:FCCall * currentCall = [[dataController callsArray] objectAtIndex:((indexPath.row - 1)/ 2)];我添加了一個異常斷點來斷開拋出所有異常,下面是它返回的內容。我明白錯誤在說什麼,但找不到原點,而且很難重新制作。iOS NSArray objectAtIndex超出範圍

CoreFoundation`-[__NSArrayM objectAtIndex:]: 
0x329cce54: push {r4, r5, r7, lr} 
0x329cce56: add r7, sp, #8 
0x329cce58: sub sp, #8 
0x329cce5a: movw r1, #62216 
0x329cce5e: mov r4, r2 
0x329cce60: movt r1, #2113 
0x329cce64: add r1, pc 
0x329cce66: ldr r1, [r1] 
0x329cce68: ldr r1, [r0, r1] 
0x329cce6a: cmp r1, r4 
0x329cce6c: bhi 0x329ccef8    ; -[__NSArrayM objectAtIndex:] + 164 
0x329cce6e: movw r0, #49640 
0x329cce72: cmp r1, #0 
0x329cce74: movt r0, #2111 
0x329cce78: add r0, pc 
0x329cce7a: ldr r0, [r0] 
0x329cce7c: ldr r0, [r0] 
0x329cce7e: beq 0x329cce9c    ; -[__NSArrayM objectAtIndex:] + 72 
0x329cce80: movw r2, #17054 
0x329cce84: subs r5, r1, #1 
0x329cce86: movt r2, #2113 
0x329cce8a: movw r3, #61062 
0x329cce8e: movt r3, #16 
0x329cce92: add r2, pc 
0x329cce94: add r3, pc 
0x329cce96: strd r4, r5, [sp] 
0x329cce9a: b  0x329cceb2    ; -[__NSArrayM objectAtIndex:] + 94 
0x329cce9c: movw r2, #17044 
0x329ccea0: movt r2, #2113 
0x329ccea4: movw r3, #61034 
0x329ccea8: movt r3, #16 
0x329cceac: add r2, pc 
0x329cceae: str r4, [sp] 
0x329cceb0: add r3, pc 
0x329cceb2: movs r1, #0 
0x329cceb4: bl  0x329dce60    ; CFStringCreateWithFormat 
0x329cceb8: bl  0x329c897c    ; CFMakeCollectable 
0x329ccebc: mov r1, r0 
0x329ccebe: movs r0, #0 
0x329ccec0: bl  0x329ffa8c    ; _CFAutoreleasePoolAddObject 
0x329ccec4: movw r2, #50122 
0x329ccec8: mov r3, r0 
0x329cceca: movt r2, #2111 
0x329ccece: movw r1, #25010 
0x329cced2: add r2, pc 
0x329cced4: movt r1, #2112 
0x329cced8: movw r0, #26280 
0x329ccedc: ldr r2, [r2] 
0x329ccede: add r1, pc 
0x329ccee0: movt r0, #2112 
0x329ccee4: ldr r1, [r1] 
0x329ccee6: movs r4, #0 
0x329ccee8: add r0, pc 
0x329cceea: str r4, [sp] 
0x329cceec: ldr r0, [r0] 
0x329cceee: ldr r2, [r2] 
0x329ccef0: blx 0x32abfeec    ; symbol stub for: -[NSMutableOrderedSet removeObjectsInRange:inOrderedSet:] 
0x329ccef4: blx 0x32abfe8c    ; symbol stub for: -[NSMutableOrderedSet removeObjectsAtIndexes:] 
0x329ccef8: movw r1, #62064 
0x329ccefc: movt r1, #2113 
0x329ccf00: movw r3, #62048 
0x329ccf04: add r1, pc 
0x329ccf06: movt r3, #2113 
0x329ccf0a: movw r2, #62048 
0x329ccf0e: ldr r1, [r1] 
0x329ccf10: add r3, pc 
0x329ccf12: movt r2, #2113 
0x329ccf16: ldr r3, [r3] 
0x329ccf18: add r2, pc 
0x329ccf1a: ldr r2, [r2] 
0x329ccf1c: ldr r1, [r0, r1] 
0x329ccf1e: ldr r3, [r0, r3] 
0x329ccf20: ldr r0, [r0, r2] 
0x329ccf22: add.w r2, r4, r1, lsr #2 
0x329ccf26: sub.w r1, r2, r3, lsr #2 
0x329ccf2a: lsrs r3, r3, #2 
0x329ccf2c: cmp r3, r2 
0x329ccf2e: it  hi 
0x329ccf30: movhi r1, r2 
0x329ccf32: ldr.w r0, [r0, r1, lsl #2] 
0x329ccf36: add sp, #8 
0x329ccf38: pop {r4, r5, r7, pc} 
0x329ccf3a: nop  
0x329ccf3c: nop  
0x329ccf3e: nop 

代碼:該刷新陣列

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    // Returns the cell for the given indexPath 
    static NSString *cellidentifier1 = @"cell1"; 
    static NSString *cellidentifier2 = @"cell2"; 

    self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"dark-background.jpg"]]; 
    self.tableView.separatorColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"dark-background.jpg"]]; 

    // Invisible Cell 
    if (indexPath.row % 2 == 0) { 

     UITableViewCell * cell2 = [theTableView dequeueReusableCellWithIdentifier:cellidentifier2]; 

     if (cell2 == nil) { 

      cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier2]; 
      [cell2.contentView setAlpha:0]; 
      [cell2 setUserInteractionEnabled:NO]; 
      [cell2 setBackgroundColor:[UIColor clearColor]]; 
     } 
     return cell2; 
    } 

    // Standard Cell  
    SideSwipeTableViewCell *cell = (SideSwipeTableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellidentifier1]; 

    if (cell == nil) { 

     cell = [[SideSwipeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier1]; 
    } 

    if ([dataController numberOfCalls] >= 1) { 

     FCCall *currentCall = [[dataController callsArray] objectAtIndex:((indexPath.row - 1)/2)]; 

     cell.callLabel.text = currentCall.call; 
     cell.locationLabel.text = currentCall.location; 
     cell.wcccaNumberLabel.text = currentCall.wcccaNumber; 
     cell.callNumberLabel.text = currentCall.callnumber; 

     // Remove leading white space from units string 
     NSString *units = [currentCall.units stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 

     cell.unitsLabel.text = units; 
     cell.stationLabel.text = currentCall.station; 
    } 
    return cell; 
} 

方法:

- (void)refreshData:(id)object success:(void (^)(NSURLRequest *request, NSURL *url, NSArray *calls))success failure:(void (^)(NSURLRequest *request, NSURL *url, NSError *error))failure 
{ 
    NSLog(@"Refresh Started"); 

    // Start the network activity indicator 
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 

    // Check to make sure we can even make an HTTP request 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.wccca.com/PITS"]]; 
    AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 
    [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 

     NSLog(@"Reachable"); 

     // Get the URL we are going to use to parse with 
     [FCDataController parserURL:[NSURL URLWithString:@"http://www.wccca.com/PITS"] completion:^(NSURL *url) { 

      NSURLRequest *parserRequest = [NSURLRequest requestWithURL:url]; 
      AFXMLRequestOperation *operation = [AFXMLRequestOperation XMLParserRequestOperationWithRequest:parserRequest success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) { 

       // Remove all data from our previous calls aray 
       [self performSelectorOnMainThread:@selector(removeCallsFromArray) withObject:nil waitUntilDone:YES]; 

       // Set the delegate for the XMLParser and start the parse operation 
       XMLParser.delegate = self; 
       BOOL successful = [XMLParser parse]; 

       // Determine if the parse operation was a success or not 
       if (!successful) { 

        // Return the failure block because the parser failed 
        failure(request, url, [FCErrors parserError]); 

        // Stop the network activity indicator 
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
       } 
       else { 

        // Return the success block 
        success(request, url, calls); 

        // Stop the network activity indicator 
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
       } 

       NSLog(@"Refresh Finished"); 

      } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser *XMLParser) { 

       NSLog(@"AFXMLOperation Error: %@", error.localizedDescription); 

       // Remove all data from our previous calls aray 
       [self performSelectorOnMainThread:@selector(removeCallsFromArray) withObject:nil waitUntilDone:YES]; 

       failure(parserRequest, url, [FCErrors badURLError]); 

       // Stop the network activity indicator 
       [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 

       NSLog(@"Refresh Finished"); 
      }]; 
      [operation start]; 
     }]; 

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 

     NSLog(@"Unreachable. AFHTTPRequestOperation Error: %@", error.localizedDescription); 

     // Remove all data from our previous calls aray 
     [self performSelectorOnMainThread:@selector(removeCallsFromArray) withObject:nil waitUntilDone:YES]; 

     failure(request, nil, [FCErrors networkError]); 

     // Stop the network activity indicator 
     [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 

     NSLog(@"Refresh Finished"); 
    }]; 
    [requestOperation start]; 
} 
+2

有一件事是肯定的:糟糕的Xcode沒有造成這種情況。 – 2013-04-26 19:59:04

回答

1

如果您的底層數據模型已改變(例如,刷新該表需要顯示數據),您需要在tableView上調用reloadData,否則它可能會請求不再存在的行的數據。

+0

當refreshData調用成功塊時,我會這樣做。 – 2013-04-26 22:03:31

+0

你可能有競爭條件。如果您的基礎數據正在更新和您的'reloadData'調用之間存在時間間隔(特別是在那些發生在不同線程上的情況下),表可能會請求不再存在的數據。你的'removeCallsFromArray'修改表格顯示的數組嗎?如果是這樣,那麼它也需要調用'reloadData'。 – vacawama 2013-04-26 22:38:37

+0

所有removeCallsFromArray所做的就是調用[array removeAllObjects]在解析xml並重新填充新數據之前清除數組。我不相信我受到競爭條件的困擾,因爲數組通過NSXML分析器操作進行填充,一旦完成,我將reloadData的成功塊傳遞迴我的視圖控制器,在那裏重新加載表。因此,直到成功塊被傳遞爲止,表不會被重新加載,直到解析器操作完成後纔會傳遞該表。 – 2013-04-27 05:21:22

相關問題