使用的Xcode-8.2.1,夫特-3.0.2,RealmSwift-2.2.0,IOS的模擬器-10:帶領域的MVVM:跨線程傳遞領域結果?
我嘗試應用使用境界MVVM模式(explained by Steve Scott here)。
一切工作,直到現在(在VIEW部分 - 見下文),我嘗試訪問viewmodel屬性。它說:Realm accessed from incorrect thread
我怎麼能仍然使MVVM模式做它的工作分離模型,視圖模型和視圖,但在同一時間,獲得領域的線程安全?
是否有辦法讓Realm結果(即Results<BalancesDataEntry>
)跨線程傳遞?
這裏是我的代碼: (問題發生在最底層,查看部之中)
// REALM-OBJECT:
import Foundation
import RealmSwift
class BalancesDataEntry: Object {
dynamic var category: String = ""
dynamic var index: Int = 0
}
MODEL:
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]) -> Void)
{
// Simulate Aysnchronous data access
DispatchQueue.global().async {
let realmThread = try! Realm()
let returnArray: [BalancesDataEntry] = Array(realmThread.objects(BalancesDataEntry.self))
completionHandler(returnArray)
}
}
}
視圖模型:
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) -> BalancesDataEntry?
{
if let entries = entries , entries.count > index {
return entries[index]
}
return nil
}
func useEntryAtIndex(_ index: Int)
{
if let entries = entries, let coordinatorDelegate = coordinatorDelegate , index < entries.count {
coordinatorDelegate.balancesViewModelDidSelectData(self, data: entries[index])
}
}
}
VIEW:
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)
{
}
}
看來問題在於你每次都要從Realm中複製數據來強制執行異步,這是非常不必要的,因爲查詢結果已經被異步更新。您可以只進行一次查詢並將結果對象存儲在模型對象中。然後你可以直接從'getEntries()'方法返回它,它總是最新的。 – ast