我的应用程序使用Swift 3.1,Realm 2.7.0作为数据库,并具有一个后台服务,该服务使用DispatchGroup控制我确定的流程。

首先,在ViewController中,我实现了Realm通知系统的实现,即NotificationToken,该系统使用addNotificationBlock方法检测已确定对象中数据的任何变化。

在那之前,一切都很好。所有更改都将调用此块。

我实现了一个使用一堆DispatchQueueDispatchGroup的新过程,这是一个示例:

这段代码只是一个示例!不要这样!

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))]

10-07 13:44