Reputation: 1976
I have a UITableView that is populated from an array of data that is parsed from an XML feed. Im struggling to find the cause of this error and was wondering if anyone can help me. The error does not occur very often. It only occurs when the array count is large, for example 10-15 objects and then once refreshed, they array is then a lower number, like 3 - 4 objects. Normally the error is thrown on this line: FCCall *currentCall = [[dataController callsArray] objectAtIndex:((indexPath.row - 1 ) / 2)]; I added an exception breakpoint to break On Throw for All Exception and below is what it returned. I understand what the error is saying but cannot find the origin and it is very difficult to re-produce.
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
Code:
- (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;
}
Method that refreshes the array:
- (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];
}
Upvotes: 1
Views: 1007
Reputation: 154583
If your underlying data model has changed (such as refreshing your data that the table needs to display), you need to call reloadData
on the tableView
, otherwise it might request data for a row that no longer exists.
Upvotes: 1