代码之家  ›  专栏  ›  技术社区  ›  RunLoop

核心数据多线程

  •  1
  • RunLoop  · 技术社区  · 14 年前

    我的应用程序首先显示一个表视图,它的数据源是一个核心数据sqlite存储。当应用程序启动时,会创建一个具有自己的存储控制器和上下文的辅助线程,以从Web获取存储中数据的更新。但是,对存储的任何结果更改都不会通知FetchedResults控制器(我假定,因为它有自己的协调器),因此该表不会随存储更改而更新。刷新主线程上的上下文最有效的方法是什么?我正在考虑跟踪在次线程上更改的任何对象的对象ID,在次线程完成时将这些对象发送到主线程,并调用“[Context RefreshObject:………]非常感谢您提供的任何帮助。

    2 回复  |  直到 9 年前
        1
  •  2
  •   Massimo Cafaro    14 年前

    在你 NSFetchedResultsController 处理表格,登记 viewDidLoad loadView 对于通知:

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:@"ContextDidSave" object:nil];
    

    当辅助线程准备好新数据时,只需像往常一样保存上下文,然后发布通知:

    [[NSNotificationCenter defaultCenter] postNotificationName:@"ContextDidSave" object:managedObjectContext];
    

    通知将在您的 未保存的结果控制器 使用以下方法:

    编辑 :在与bbum进行深入讨论后,在正确考虑多线程的情况下修改了下面的方法。

    - (void)contextDidSave:(NSNotification *)notification
    {
    
        SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
        [[[[UIApplication sharedApplication] delegate] managedObjectContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES];
    
    }
    

    对于UI更新,可以使用 未保存的结果控制器 委托方法。

    最后,记住在 dealloc 方法 未保存的结果控制器 下列内容:

    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
        2
  •  2
  •   bbum    14 年前

    未给定的答案无法正确处理线程。特别是,文件规定(强调我的):

    如果应用程序具有图形 用户界面,建议 您接收与用户相关的事件和 从您的 应用程序的主线程。这个 方法有助于避免同步 与处理用户相关的问题 事件和绘图窗口内容。 一些框架,如Cocoa, 通常需要这种行为 但是 即使对于那些不这样做的人, 主线程上的此行为具有 简化逻辑的优点 用于管理用户界面。

    通知观察员将在通知最初发布到的任何线程上被激发。因此,不能调用InstableView的 reloadData 直接来自后台线程发布的通知。

    根本不需要使用通知。在后台线程中,当准备更新用户界面时,可以使用许多机制中的任何一种来重新加载主线程中的数据——在管理主事件循环和用户界面的线程中。

    [tableView performSelectorOnMainThread: @selector(reloadData)
               withObject: nil waitUntilDone: YES];
    

    您也可以使用GrandCentralDispatch或nsOperation来执行类似的操作。