title: MVVM with realm: Passing Realm-results across threads?
body: <p>Using Xcode-8.2.1, Swift-3.0.2, RealmSwift-2.2.0, iOS-Simulator-10:</p>
  
  <p>I try applying the MVVM pattern (<a href="https://www.youtube.com/watch?v=9VojuJpUuE8" rel="nofollow noreferrer">explained by Steve Scott here</a>) using Realm.</p>
  
  <p>Everything works until the moment (inside the VIEW-part - see below) where I try to access a viewmodel-property. It says: <code>Realm accessed from incorrect thread</code></p>
  
  <p>How could I still make the MVVM-pattern do its job of separating model, view-model and view but, on the same time, get thread-safety with realm ?</p>
  
  <p>Is there a way to make Realm-results (i.e. <code>Results&lt;BalancesDataEntry&gt;</code>) being passed across threads ??</p>
  
  <p>Here is my code:
  (the issue happens at the very bottom, inside the View-part)</p>
  
  <pre><code>// REALM-OBJECT:
  
  import Foundation
  import RealmSwift
  
  class BalancesDataEntry: Object {
  
      dynamic var category: String = ""
      dynamic var index: Int = 0  
  }
  </code></pre>
  
  <p>MODEL:</p>
  
  <pre><code>import Foundation
  import RealmSwift
  
  class MVVMCBalancesModel: BalancesModel
  {
  
      fileprivate var entries = [BalancesDataEntry]()
      let realm = try! Realm()
  
      init() {
          self.createDataEntries()
      }
  
      fileprivate func createDataEntries() {
  
          let myBalance = BalancesDataEntry()
          myBalance.index = 0
          myBalance.category = "Love"
  
          try! self.realm.write {
  
              self.realm.deleteAll()
              self.realm.add(myBalance)
          }
      }
  
      func getEntries(_ completionHandler: @escaping (_ entries: [BalancesDataEntry]) -&gt; Void)
      {
          // Simulate Aysnchronous data access
          DispatchQueue.global().async {
  
              let realmThread = try! Realm()
              let returnArray: [BalancesDataEntry] = Array(realmThread.objects(BalancesDataEntry.self))
              completionHandler(returnArray)
          }
      }
  }
  </code></pre>
  
  <p>VIEW-MODEL:</p>
  
  <pre><code>import Foundation
  import RealmSwift
  
  class MVVMCBalancesViewModel: BalancesViewModel
  {
      weak var viewDelegate: BalancesViewModelViewDelegate?
      weak var coordinatorDelegate: BalancesViewModelCoordinatorDelegate?
  
      fileprivate var entries: [BalancesDataEntry]? {
          didSet {
              viewDelegate?.entriesDidChange(viewModel: self)
          }
      }
  
      var model: BalancesModel? {
          didSet {
              entries = nil;
              model?.getEntries({ (myEntries) in
                  self.entries = myEntries
              })
          }
      }
  
      var title: String {
          return "My Balances"
      }
  
      var numberOfEntries: Int {
          if let entries = entries {
              return entries.count
          }
          return 0
      }
  
      func entryAtIndex(_ index: Int) -&gt; BalancesDataEntry?
      {
          if let entries = entries , entries.count &gt; index {
  
              return entries[index]
          }
          return nil
      }
  
      func useEntryAtIndex(_ index: Int)
      {
          if let entries = entries, let coordinatorDelegate = coordinatorDelegate  , index &lt; entries.count {
              coordinatorDelegate.balancesViewModelDidSelectData(self, data: entries[index])
          }
      }
  }
  </code></pre>
  
  <p>VIEW:</p>
  
  <pre><code>import UIKit
  
  class MVVMCBalancesViewController: UIViewController {
  
      @IBOutlet weak var label1Outlet: UILabel!
      @IBOutlet weak var label2Outlet: UILabel!
  
     var viewModel: BalancesViewModel? {
          willSet {
              viewModel?.viewDelegate = nil
          }
          didSet {
              viewModel?.viewDelegate = self
              refreshDisplay()
          }
      }
  
     var isLoaded: Bool = false
  
     func refreshDisplay()
     {
          if let viewModel = viewModel , isLoaded {
  
              // !!!!!!! HERE IS THE ISSUE: Realm accessed from incorrect thread !!!!
              self.label1Outlet.text = viewModel.entryAtIndex(0)?.category
              self.label2Outlet.text = viewModel.entryAtIndex(1)?.category
          } else {
  
          }
      }
  
      override func viewDidLoad()
      {
          super.viewDidLoad()
  
          isLoaded = true
          refreshDisplay();
      }
  
  }
  
  extension MVVMCBalancesViewController: BalancesViewModelViewDelegate
  {
      func entriesDidChange(viewModel: BalancesViewModel)
      {
  
      }
  }
  </code></pre>