【问题标题】:NSNotification observer - NSManagedObjectContextDidSaveNSNotification 观察者 - NSManagedObjectContextDidSave
【发布时间】:2015-10-05 03:03:32
【问题描述】:

您好,我希望有人可以帮助我解决这个问题。当用户首次登录我的应用程序时,会进行 API 调用,该调用将在 Web 服务器上的数据库中获取该用户的现有数据。当他们第一次登录时(如果成功),我转到另一个视图控制器,它显示一个进度指示器,当下载的数据完全保存到 Core Data 时停止动画,然后转到应用程序的主 vc(用户可以开始使用应用程序)。

我宁愿拥有一个实时指示器,而不是进度指示器,例如每次将项目保存到核心数据时都会更新的当前下载项目的计数,但在这种情况下,我别无选择,只能使用 NSNotificationCenter监听从 API 下载的每个项目何时保存到核心数据。到目前为止,我有:

override func viewDidAppear(animated: Bool) {
   super.viewDidAppear(true)
   NSNotificationCenter.defaultCenter().addObserver(self,   selector:"contextDidSave:", name: NSManagedObjectContextDidSaveNotification, object:nil)
} 

func contextDidSave(notification: NSNotification) {
  if notification.name == NSManagedObjectContextDidSaveNotification {
    var c = CoreMessage.getMessages(self.moc, ascending:true).count
    //the println works - i see the updated count
    println(c)
    //this doesnt work, the lbl does not get updated
    self.labelCount.text = "\(c)"
  }
}

我也尝试像这样更新标签:

dispatch_async(dispatch_get_main_queue(), { () -> Void in
  self.labelCount.text = "\(c)"
})

谁能解释我可能做错了什么?

【问题讨论】:

  • 也许您的标签没有连接到 UI?顺便说一句 - 在每次插入后保存上下文并不高效 - 改用批处理:stackoverflow.com/questions/4145888/ios-coredata-batch-insert
  • 谢谢,它通过 IB 插座连接,所以没有问题。我认为这与在单独线程上执行的工作有关,只是不确定为什么我无法访问主线程来更新标签。感谢您的批处理评论,但我将初始下载限制为 500 条记录,我分析这些记录需要不到 3 秒的时间,并且用户永远不需要再次获取那么多记录。
  • 您是否尝试过检查 NSManagedObjectContext 是否在主线程上启动 - NSThread.isMainThread()
  • 为什么要在 viewDidAppear 中设置观察者?

标签: ios objective-c swift core-data nsnotificationcenter


【解决方案1】:

这里有几件事。

  1. 您很可能遇到线程问题。打开 CurrencyDebug 标志并确认。这将影响 UI 的构成要素。
  2. 您不想在此处进行提取。首先,您的 fetch 会减慢导入速度。更糟糕的是,您已经有了汇总数据所需的数据。

注意:你的 if 与字符串比较也是不需要的。

您收到的通知包含-userInfo 字典。该字典内部是三个集合对象,表示在引用的保存中插入、更新和删除的内容。您可以而且应该只查询这些集合以查看已更改的内容并从那里更新您的用户界面。

【讨论】:

  • 我相信你在线程方面是正确的。我做了更多的研究,看起来 MOC 不是线程安全的,相反我应该在创建核心数据记录时传递 objectID。我将打开 concurrencydebug 标志以确认这一点并报告回来。问题似乎出在 getMessages 函数上,我基本上是从 API 获取所有消息,并使用从该方法中的单例实例化的 MOC 将它们保存到核心数据。
  • 是的,这是一个线程问题。但是再次,您根本不需要获取。阅读我的其余答案。
  • 为了提供更多上下文,这是一个提供短信但没有 iOS 客户端的 VOIP 公司的消息应用程序。相反,人们使用他们的网络客户端来发送和接收短信。因此,当他们第一次登录我正在构建的应用程序时,我使用 NSURLConnection 异步请求下载他们所有现有的消息,并将每条下载的消息保存到 CoreData 中。下载/保存完成后,应用程序会转到消息摘要视图(非常类似于 iMessage 中的消息应用程序表格视图)。
  • 这仅在第一次登录时发生。 “getMessages”这个名字可能有点误导,它基本上只是调用 API 并保存到核心数据——我实际上并没有获取核心数据消息。一旦我弄清楚了,我会尽快发布我的解决方案,但我相信我需要初始化一个私有 MOC(而不是总是使用主线程的常规 MOC)并在保存/更新我从 API 获取的对象时使用执行块所以确保主线程不受影响。
  • 我已经在答案中解释了更新 UI 的解决方案。数据处理应始终由私有 MOC 完成,以避免阻塞 UI。更新 UI 必须始终在主线程上完成,因为 UI 不是线程安全的。祝你好运。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 2011-09-22
  • 2015-04-25
相关资源
最近更新 更多