草庐IT

ios - NSFetchedResultsController 一致延迟更新 UITableView 单元格;插入立即起作用

coder 2023-09-21 原文

我有一个连接到 NSFetchedResultsControllerUITableView(带有自定义单元格,如果这很重要)。我的应用程序还使用推送通知。当远程通知到达时,我分两个阶段更新我的(核心)数据模型:

1) 获取标题(带有一些自定义数据)并将其存储为新的核心数据 Entity。这里我调用了 NSManagedObjectContext save()NSFetchedResultsController 获取插入并使用 NSFetchedResultsChangeType=NSFetchedResultsChangeInsert 触发它的委托(delegate)方法 didChangeObject。 tableview 立即更新。 (插入新行)

2) 通过NSURLSession下载更多与cell相关的内容,插入到上面的Entity中,再次调用save()方法NSFetchedResultsController 再次获取更新并使用 NSFetchedResultsChangeType=NSFetchedResultsChangeUpdate 触发它的委托(delegate)方法 didChangeObject。这是我调用 configureCell 方法的地方。 tableView 已更新,但持续延迟约 10 秒。

在这两个阶段(下载-上下文保存-更新 TableView )需要显示的数据已经已经被核心数据持久化了。 (例如,在我的 configureCell.. 方法中,我知道我没有将任何单元格标签设置为 nil 或类似内容。

我的 NSFetchedResultsController 委托(delegate)方法:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.mainTableView beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.mainTableView endUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.mainTableView;

switch(type) {

    case NSFetchedResultsChangeInsert:
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(MessageTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
    }
}

我在 case NSFetchedResultsChangeUpdate: 中尝试过的其他事情

  1. 尝试在上下文保存之前调用processPendingChanges
  2. 调用 reloadRowsAtIndexPaths 而不是直接调用 configureCell
  3. 尝试将 update.. 方法包装在 beginUpdatesendUpdates 中(即使我已经有一对可以完成这项工作)
  4. [tableView reloadData]
  5. numberOfRowsInSection 不为 0!
  6. NSFetchedResultsController 委托(delegate)方法仅在主线程上运行。

简而言之,所有(?)正确的委托(delegate)方法都被正确调用。然而,我在更新单元格时看到一致的 ~10 秒延迟。然而,插入几乎是瞬间发生的。有任何想法吗?

最佳答案

@Paulw11 关于 dispatch_async... 的评论让我朝着正确的方向前进。问题在于我一直在两个不同的线程中使用相同的 ManagedObjectContext 对象,即使它们不会同时访问它。一旦我在主队列上调度了我的 save 调用(在后台线程上)(通过将其包装在 dispatch_async(dispatch_get_main_queue,^{ UIUpdate code here });),延迟消失了。一种可能的解释是,在后台线程上调用 save 会导致在后台线程上调用委托(delegate)方法。

无论如何,回到解决方案 - 永远不要在多个线程之间共享相同的 ManagedObjectContext 对象。 Use parent/child context relationships如果您要在多个线程中更新核心日期。 NSFetchedResultsController 也很适合这种模式。

关于ios - NSFetchedResultsController 一致延迟更新 UITableView 单元格;插入立即起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28957936/

有关ios - NSFetchedResultsController 一致延迟更新 UITableView 单元格;插入立即起作用的更多相关文章

  1. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  4. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  5. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  6. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  7. ruby - 单元测试文件 I/O 方法 - 2

    我对单元测试还是比较陌生。我用Ruby编写了一个类,它接受一个文件,在该文件中搜索给定的Regex模式,替换它,然后将更改保存回文件。我希望能够为此方法编写单元测试,但我不知道我将如何去做。有人能告诉我我们如何对处理文件i/o的方法进行单元测试吗? 最佳答案 看看这个HowdoIunit-testsavingfiletothedisk?基本上这个想法是一样的,文件系统是你的类的依赖。所以引入一个可以在你的单元测试中模拟的角色/接口(interface)(这样你在单元测试时就没有依赖性);角色中的方法应该是您从文件系统中需要的所有东西

  8. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

  9. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  10. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

随机推荐