如何更新 UI 以显示 Core Data 长时间运行的进程?

Posted

技术标签:

【中文标题】如何更新 UI 以显示 Core Data 长时间运行的进程?【英文标题】:How to update UI to show Core Data long running process? 【发布时间】:2011-12-23 16:45:30 【问题描述】:

我的应用中有一项操作需要使用 Core Data 进行大的、有时是几秒钟的更新。因为我想做的不仅仅是显示一个微调器,我想向最终用户显示一个进度条。然而,这带来了一些问题,因为 Core Data 坚持在主线程上运行。我试图将 Core Data 放在带有 dispatch_async 的后台线程上,结果是灾难性的。问题是 UIKit 也想在主线程上运行,更糟糕的是,它只在当前线程结束后才更新。这会导致进度条仅在完成所有处理后才会更新!

如何更新 UI 并安全地更新我的数据?

NSArray* items = [[response.data objectForKey:@"result"] objectForKey:@"items"];

NSManagedObjectContext* context = [RBGameItemController sharedInstance].managedObjectContext;

int itemCount = [items count];

for (int i = 0; i < itemCount; i++) 
    float progress = ((float)i/(float)itemCount)*0.95f;
    self.progressView.progress = 0.5f + progress; 

    id item = [items objectAtIndex:i];
    [GameItem gameItemFromDictionary:item inManagedObjectContext:context];


NSError* error = nil;
[context save:&error];

【问题讨论】:

【参考方案1】:

Core Data 不需要在主线程上工作,只需要为每个单独的线程都有一个 NSManagedObjectContext。在单独的线程(使用 NSOperationQueue)上创建一个具有相同后备存储的新 NSManagedObjectContext 并在那里进行处理。从备用线程保存 NSManagedObjectContext 后,主线程的上下文将从后备存储中获取更改。要从备用线程更新您的 UI,请使用

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

这是 NSObject 上的一个方法。祝你好运,如果有任何不清楚的地方,请发表评论。

【讨论】:

我在发布之前确实尝试过这个,但是收到一个错误,说我无法从另一个 managedObjectContext 中删除对象。 当您在上下文之间传递 NSManagedObjects 时会导致该错误。如果您在备用线程的上下文中工作,则必须在该上下文中查询要修改的对象——每个线程必须完全独立地工作。您唯一可以共享的是后备存储。 这是把它放在后台线程的问题。我修改了代码以接受上下文作为参数,并传递了在我的dispatch_async 块中创建的新上下文。然后我创建了一个新的 GCD 线程在主线程上执行以更新 UI。像魅力一样工作! :D

以上是关于如何更新 UI 以显示 Core Data 长时间运行的进程?的主要内容,如果未能解决你的问题,请参考以下文章

将 JSON 数据插入 Core Data 存储需要很长时间

让 Shiny 更新 ui 并在之后运行长时间计算

在 .Net Core 的另一个线程上调用函数

当一个线程完成任务而另一个线程正在运行时,有没有办法更新 Web 表单 UI

在 Core Data 中 10 秒后杀死一个任务

SqlDataAdapter.Fill 方法不会给出任何错误,但也不会返回任何数据以用于长时间运行的查询 ado.net core SQL Server