UITableView endUpdates not being called in dispatch_async

一世执手 提交于 2019-12-13 04:38:32

问题


I have several table views that send JSON requests to a server, store the results in core data, and display them using an NSFetchedResultsController. I was experimenting with GCD as follows:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    // Perform JSON requests.
    dispatch_async(dispatch_get_main_queue(), ^{
        [theTableView reloadData];
    });
});

However, this would cause some weird things to happen in the UI. New managed objects would render blank cells, deleted managed objects would cause cells to overlap, etc.

However, I found that if I did this, everything would render correctly.:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [theTableView endUpdates];
    });
}

What I wanted to know is, why is this necessary? Since it fires as a result of [theTableView reloadData], why isn't it automatically included in the main queue? I thought maybe that it was because I didn't call it explicitly. In that case, do I have to wrap all my functions similarly?


回答1:


I assume that you use the main NSManagedObjectContext from a separate thread, which is not allowed. For a background import, you have to create a separate managed object context, import the objects in that context, and then save/merge the changes to the main context.

One possibility is to use a child context of the main managed object context:

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc]
                         initWithConcurrencyType:NSPrivateQueueConcurrencyType];
childContext.parentContext = mainManagedObjectContext;
[childContext performBlock:^{
    // Perform JSON requests.
    // Save objects to childContext.

    NSError *error;
    BOOL success = [childContext save:&error];
}];

A context of the "private concurrency type" creates its own queue/thread, so that the performBlock is executed in the background (and you need/must not create a queue yourself).

Saving childContext merges the changes up to the parent mainManagedObjectContext. This should be sufficent for the fetched results controller to get notified of the changes, and update the table view.

See Core Data Release Notes for OS X v10.7 and iOS 5.0 for more information about managed object context concurrency, and nested contexts.




回答2:


was

 [theTableView beginUpdates]

written anywhere in the code? Try removing it. I suspect the UI weird stuff is happening because beginUpdates is already asynchronous itself (not blocking the main thread) for funky UITableView animations to take place.



来源:https://stackoverflow.com/questions/19271001/uitableview-endupdates-not-being-called-in-dispatch-async

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!