2017-05-29 71 views
1

我的應用程序使用Swift 3.1,Realm 2.7.0作爲數據庫並具有使用DispatchGroup來控制我確定進程的流的後臺服務。第一DispatchGroup和Realm

第一件事,在我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運行時更新。

謝謝!

回答

-1

解決方案非常簡單,您只需要在主線程上運行更新即可。

foo.progress = { newValueInt in 
    DispatchQueue.main.sync { 
     let realm = try! Realm() 
     try! realm.write { 
     realm 
      .object(ofType: Some.self, forPrimaryKey: id) 
      .someValue = newValueInt 
     } 
    } 
    } 
+0

這似乎....錯了。 – EpicPandaForce

+0

告訴我爲什麼。給我理由。 –

+0

交易完成後,Realm是否有任何方式通知所有tokenBlocks?我不這麼認爲。 –

4

下面是一個使用你的代碼,因爲你沒有提供的空白處填入一個完整的應用程序,並通知塊被正確地調用:

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

這不是我的源代碼。只是巧合。既不是靈感。我從來沒有碰過這個代碼。 :) –

+0

有沒有理由看到這個工作,因爲這段代碼調度到後臺隊列,我這樣做,它只是修改後在主線程上調度。 –

+0

在後臺線程中寫入將在UI線程上通知Realm實例 和結果/對象的通知令牌(如果已經發生更改)。無需在UI線程上寫入Realm。 – EpicPandaForce