[英]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.