Hi,

I have a UITableView, with a datasource using array of NSDictionary objects for 
the view (it used to be more complicated, but I've changed it to track down a 
bug).

I have a single method which builds the array of dictionary's:

- (void)reloadInspectionResults
{
        if (dispatch_get_current_queue() != dispatch_get_main_queue()) {
                @throw [NSException exceptionWithName:@"call from wrong thread" 
reason:@"Tried to reload inspection data from a background thread." 
userInfo:nil];      
        }
        
        
        self.inspectionsResultsController = /* allocate/configure/execute fetch 
*/
        self.inspections = inspectionsResultsController.fetchedObjects;
        
        self.tableViewContent = [NSMutableArray array];
        for (Inspection *inspection in self.inspections) {
                [self.tableViewContent addObject:[NSDictionary 
dictionaryWithObjectsAndKeys:inspection.display_name, @"display_name", 
inspection.display_inspection_datetime, @"display_inspection_datetime", 
[inspection objectID], @"objectID", nil]];
        }
        [self.inspectionsView reloadData];
        [self.inspectionsView setNeedsDisplay];
}

- (NSInteger)tableView:(UITableView *)tableView 
numberOfRowsInSection:(NSInteger)section
{
        return self.tableViewContent.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView 
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
        /* return a new cell, filled with values from self.tableViewContent */
}


I have a background thread, which downloads data from the server and updates 
the contents of the managed object context, and informs my table view to reload 
it's data. When the user tap's a row in the UITableView, I'm doing this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath 
*)indexPath
{
        NSLog(@"%@", self.inspections);
        NSLog(@"%@", self.tableViewContent);
        
        NSManagedObjectID *objectID = [[self.tableViewContent 
objectAtIndex:indexPath.row] valueForKey:@"objectID"];
        Inspection *inspection = (Inspection *)[[MOC mainContext] 
objectWithID:objectID];

        /* do stuff with inspection object, which is often the wrong object by 
one index, or crashes if the last item was tapped */
}

For days we've been tracking down an edge case bug where tapping a row in the 
UITableView either opens the wrong item or crashes. I don't fully understand 
what's going on, but when an item is removed from the array, the UITableView 
does not see the new data, even though the *only place* where this array is 
created immediately reloads the data and tries to trigger drawRect via 
setNeedsDisplay.

Sometimes it takes 10 or 20 minutes for the UITableView to correctly remove the 
item from the list. This is dependent on a background thread which uploads JPEG 
data over 3G. Activating airplane mode while it's uploading the JPEG causes the 
bug to stick around indefenently. The table view continues to show draw the 
wrong data even after pushing a new view controller, doing stuff which will 
trigger low memory warnings (taking photos, doing lots of stuff with the new 
NSImage, etc), and going back to this view (causing the reloadInspectionResults 
to be triggered *again* due to low memory warning).

Reading online, I've seen suggestions that this kind of stuff will be caused if 
you try to reload the table view from a background thread. As you can see, I 
added my own exception to check for that — this exception is never triggered.

The array is definitely not modified in any other place. I only defined that 
instance variable while trying to track down this bug.

Tapping the last item in the view while it's out of sync will crash the app. 
Tapping any other item in the view will cause the wrong database record to be 
opened, this is currently causing employees of our client to enter data into 
the wrong database record, triggering invalid documents to be sent to other 
businesses. By government regulation, our client is legally required to 
distribute these documents within 48 hours of collecting the data, which is now 
impossible and causing major trust issues.

Does anyone have any ideas? I've run out, and am planning to move all network 
activity to the main thread (even though it may have to upload a several 
megabytes over 3G), to workaround this bug.

- Abhi_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to