领域通知令牌在后台线程
我试图在后台线程上获取领域数据并添加通知块(iOS,Swift)。
基本示例:
func initNotificationToken() { DispatchQueue.global(qos: .background).async { let realm = try! Realm() results = self.getRealmResults() notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in switch changes { case .initial: self?.initializeDataSource() break case .update(_, let deletions, let insertions, let modifications): self?.updateDataSource(deletions: deletions, insertions: insertions, modifications: modifications) break case .error(let error): fatalError("\(error)") break } } } } func initializeDataSource() { // process the result set data DispatchQueue.main.async(execute: { () -> Void in // update UI }) } func updateDataSource(deletions: [Int], insertions: [Int], modifications: [Int]) { // process the changes in the result set data DispatchQueue.main.async(execute: { () -> Void in // update UI }) }
当这样做,我得到
'Can only add notification blocks from within runloops'
我必须对返回的数据进行更广泛的处理,并且在处理完成后更新UI时只想回到主线程。
另一种方法可能是在后台线程更新之后重新获取数据,然后进行处理,但感觉像是可以避免的开销。
有关解决此问题的最佳做法的任何build议?
要在后台线程上添加通知,您必须在该线程上手动运行一个运行循环,并从该运行循环的调用中添加通知:
class Stuff { var token: NotificationToken? = nil var notificationRunLoop: CFRunLoop? = nil func initNotificationToken() { DispatchQueue.global(qos: .background).async { // Capture a reference to the runloop so that we can stop running it later notificationRunLoop = CFRunLoopGetCurrent() CFRunLoopPerformBlock(notificationRunLoop, CFRunLoopMode.defaultMode.rawValue) { let realm = try! Realm() results = self.getRealmResults() // Add the notification from within a block executed by the // runloop so that Realm can verify that there is actually a // runloop running on the current thread token = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in // ... } } // Run the runloop on this thread until we tell it to stop CFRunLoopRun() } } deinit { token?.stop() if let runloop = notificationRunLoop { CFRunLoopStop(runloop) } } }
GCD不在其工作线程上使用运行循环,所以任何基于将块分派到当前线程的运行循环(比如Realm的通知)都不会被调用。 为了避免让通知悄无声息地做不了任何事情,Realm试图检查这个,不幸的是PerformBlock需要跳舞。
- Swift 3:Transfer Utility enumerateToAssignBlocks方法签名
- ? 在Xcode 6 Beta 6中没有名为'subscript'的成员
- 收到错误:Error Domain = com.facebook.sdk.core Code = 8“(null)”
- Firebase从2.5.1升级到3.2.1
- 用use_frameworks签名错误! 和独特的configuration文件
- 如何使用Swift,iOS 7设置rootViewController
- 如何在Swift中的视图控制器之间传递数据?
- 在启用所有exception断点之后,始终停止在应用程序委托中
- 在Swift中从JSON数组获取值