我的应用程序使用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.
}
}
}
问题是:当方法
addNotificationBlock
运行时,没有调用Bar.progress
,并且未更新添加在其通知块上的对象。谢谢!
最佳答案
这是一个使用您的代码的完整应用程序,填补了您未提供的空白,并且正确调用了通知块:
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))]