所以我有一個singleton類管理登錄到我的應用程序中的當前用戶。帶單體的領域線程安全對象
它看起來像這樣
class SessionManager {
static let shared = SessionManager()
var loggedInUser: User?
}
的問題是,如果我想從後臺線程獲取用戶對象,我不能,因爲我得到以下異常:
'RLMException', reason: 'Realm accessed from incorrect thread.'
一些谷歌搜索後,我發現線程安全參考。所以我改變了我的班是這樣,而不是:
class SessionManager {
static let shared = SessionManager()
private var threadSafeUser: ThreadSafeReference<User>?
var loggedInUser: User? {
get {
if nil === self.threadSafeUser {
return nil
} else {
let realm = try! Realm()
return realm.resolve(self.threadSafeUser!)!
}
}
set {
if nil === newValue {
self.threadSafeUser = nil
} else {
self.threadSafeUser = ThreadSafeReference(to: newValue!)
}
}
}
}
我的想法是,我在內部持有的引用是線程安全的,那麼只要我獲取用戶對象,我解決的對象。但是還是不行,因爲你只能解決ThreadSafeReference一次:
'RLMException', reason: 'Can only resolve a thread safe reference once.'
我也試過getter中一次解決它,但你得到的第一個問題,如果你從不同的線程來引用解析對象它在哪裏解決。
目前我能想到的兩個選項:
我一直爲每個線程參考,並傳回正確的螺紋用戶對象(不是100%肯定我該怎麼做,只是一種理論在的時刻)
我可以讓我的設置/獲取調度到主線程同步獲取對象。所以我總是從主線抓住它。我可能無法寫入更改對象,但也許我可以閱讀?不知道這實際上是誠實的。
我100%確定這是以前解決的問題,因爲問題的普遍性如何。
所以同胞領域的用戶,我該如何解決這個問題?
編輯:問題已解決,感謝David下面。對於S.O的用戶來說,這是我最後做的。
class SessionManager {
static let shared = SessionManager()
private var loggedInUserId: Int?
var loggedInUser: User? {
get {
if nil == loggedInUserId {
return nil
}
let realm = try! Realm()
return realm.object(ofType: User.self, forPrimaryKey: loggedInUserId)
}
set {
if nil == newValue {
loggedInUserId = nil
} else {
loggedInUserId = newValue!.id
}
}
}
}
它可能需要一些清理(零檢查可以寫得更好),但這是我採取的基本方法。
這使我可以像普通對象一樣對待loggedInUser
屬性,每當我讀取它時,它會從領域(線程安全)獲取新引用,並且如果我想設置新用戶(即登錄後) ,我只能loggedInUser = newUser
和二傳手處理如何堅持它。
所以要確認(我是新太線程,對不起),而不是'var user'屬性,我會更好有一個'var userId'屬性持有對象的主鍵,然後做一個計算屬性getter實例化領域實例並獲取對象,每次我想獲取當前用戶? – TRG
是的,這是正確的。您應該只保留對可以唯一標識您的Realm對象的非Realm對象的引用(主鍵是此的最佳候選對象),以便您可以輕鬆安全地通過線程之間的引用。正如上面所解釋的,我通常只是簡單地創建對領域的新引用,無論我的代碼是否可能更改線程,但計算屬性也可以工作,所以值得一試。 –
謝謝大衛,我會給它一個。 :) – TRG