簡體   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