[英]DispatchGroup and Realm
我的应用程序使用Swift
3.1, Realm
2.7.0作为数据库,并有一个后台服务,它使用DispatchGroup
来控制我确定的进程流。
首先,在我的ViewController
我做了一个Realm
通知系统的实现,知道为NotificationToken
,它使用addNotificationBlock
方法来检测确定对象中的任何数据更改。
在那之前,一切都很好。 所有更改都会调用此块。
我已经实现了一个使用一堆DispatchQueue
和DispatchGroup
的新进程,这是一个例子:
这段代码只是一个样本! 不要这样做!
DispatchQueue.global(qos: .background).async {
autoreleasepool {
//Other stuff...
let id = 1337
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
DispatchQueue(label: "Process").sync {
let foo = Bar()
foo.progress = { newValueInt in
let realm = try! Realm()
try! realm.write {
realm
.object(ofType: Some.self, forPrimaryKey: id)
.someValue = newValueInt
}
}
foo.completed = {
dispatchGroup.leave()
}
foo.doSomethingAsync()
}
dispatchGroup.notify(queue: DispatchQueue.global(qos: .background)) {
//Process completed.
}
}
}
问题是:当方法Bar.progress
运行时,不调用addNotificationBlock
并且在其通知块上添加的Object不会更新。
谢谢!
这是一个完整的应用程序,它使用您的代码,填写您未提供的空白,并正确调用通知块:
import UIKit
import RealmSwift
class Bar {
var progress: ((Int) -> Void)?
var completed: (() -> Void)?
func doSomethingAsync() {
for delay in 1...100 {
// Span these 100 updates over 10 seconds
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + Double(delay) / 10) {
self.progress?(delay)
if delay == 100 {
self.completed?()
}
}
}
}
init() {}
}
class Some: Object {
dynamic var id = 0
dynamic var someValue = 0
override static func primaryKey() -> String? {
return "id"
}
}
func bgTask() {
DispatchQueue.global(qos: .background).async {
autoreleasepool {
//Other stuff...
let id = 1337
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
DispatchQueue(label: "Process").sync {
let foo = Bar()
foo.progress = { newValueInt in
let realm = try! Realm()
try! realm.write {
realm
.object(ofType: Some.self, forPrimaryKey: id)!
.someValue = newValueInt
}
}
foo.completed = {
dispatchGroup.leave()
}
foo.doSomethingAsync()
}
dispatchGroup.notify(queue: .global(qos: .background)) {
//Process completed.
}
}
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var notificationToken: NotificationToken!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
_ = try? FileManager.default.removeItem(at: Realm.Configuration.defaultConfiguration.fileURL!)
let realm = try! Realm()
let some = Some()
try! realm.write {
some.id = 1337
realm.add(some)
}
notificationToken = some.addNotificationBlock { change in
switch change {
case .change(let properties):
print(properties)
case .error(let error):
print("An error occurred: \(error)")
case .deleted:
print("The object was deleted.")
}
}
bgTask()
return true
}
}
此日志(为简洁而截断):
[RealmSwift.PropertyChange(name: "someValue", oldValue: Optional(0), newValue: Optional(1))]
[RealmSwift.PropertyChange(name: "someValue", oldValue: Optional(1), newValue: Optional(2))]
[RealmSwift.PropertyChange(name: "someValue", oldValue: Optional(2), newValue: Optional(3))]
[RealmSwift.PropertyChange(name: "someValue", oldValue: Optional(3), newValue: Optional(4))]
[RealmSwift.PropertyChange(name: "someValue", oldValue: Optional(4), newValue: Optional(5))]
...
[RealmSwift.PropertyChange(name: "someValue", oldValue: Optional(98), newValue: Optional(97))]
[RealmSwift.PropertyChange(name: "someValue", oldValue: Optional(97), newValue: Optional(100))]
解决方案非常简单,您只需要在主线程上运行更新。
foo.progress = { newValueInt in
DispatchQueue.main.sync {
let realm = try! Realm()
try! realm.write {
realm
.object(ofType: Some.self, forPrimaryKey: id)
.someValue = newValueInt
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.