繁体   English   中英

DispatchGroup和Realm

[英]DispatchGroup and Realm

我的应用程序使用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.
    }

  }

}

问题是:当方法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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM