[英]Periodically save an object in Realm
我有一個名為Trip
的Realm對象。 它存儲用戶運動的數據。
class Trip: Object {
dynamic var id: Int = 0
dynamic var startTimestamp: Int64 = 0
dynamic var endTimestamp: Int64 = 0
dynamic var distance: Double = 0.0
dynamic var calories: Double = 0.0
dynamic var averageSpeed: Double = 0.0
}
在視圖控制器中,我保留了一個名為trip
的類級變量。
fileprivate var trip: Trip?
每當用戶開始旅程時,我都會初始化一個Trip
對象並將其分配給該變量。
trip = Trip()
在用戶的整個移動過程中,我不斷使用數據更新此trip
對象。
我需要每1分鍾將此數據保存到Realm數據庫中。 所以我運行一個計時器。
Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(save()), userInfo: nil, repeats: true)
它執行一個功能將此對象保存在后台線程中。
fileprivate func save() {
do {
DispatchQueue(label: "RealmBackgroundThread").async {
autoreleasepool {
let realm = try! Realm()
try! realm.write {
realm.add(self.trip!, update: true)
}
}
}
} catch {
}
}
到這里為止,一切正常。 問題是第一次保存后,當我嘗試再次訪問該trip
對象時,它崩潰並顯示以下錯誤。
libc ++ abi.dylib:以類型為realm :: IncorrectThreadException的未捕獲異常終止:從錯誤線程訪問的領域。
我認為發生這種情況是因為我打開一個新的Realm
將該對象保存在后台線程中。 我知道Realm不是線程安全的。
但是我不確定如何解決這個問題。 保存后,如何繼續使用相同的trip
對象?
要引用Realm的文檔中有關跨線程傳遞實例的信息 :
Realm
,Results
或List
實例或Object
托管實例是線程限制的,這意味着它們只能在創建它們的線程上使用,否則會引發異常。
在您的情況下, self.trip
是Object
子類的托管實例,您似乎同時從主線程和在save()
方法中創建的串行分派隊列中反復訪問它。 重要的是要記住,對DispatchQueue.async
的調用將導致您的代碼在不同線程上執行,具體取決於Grand Central Dispatch的想法。 也就是說,兩個連續的呼叫,例如……
DispatchQueue(label: "RealmBackgroundThread").async {
// work
}
……通常會導致在兩個不同線程上執行工作。
Realm關於跨線程傳遞實例的文檔包含一個示例,該示例說明如何跨線程將線程安全引用傳遞給對象,並在目標線程上的Realm
實例中解析該對象。
在您的情況下很難提供更具體的建議,因為我不清楚您要使用save()
方法做什么以及為什么要在計時器上調用它的原因。 只能在寫事務中修改托管Object
實例(從Realm檢索到的實例,或者已經添加到Realm的實例),因此對self.trip
任何修改都需要在save()
打開的寫事務中執行save()
以使其達到任何目的的方法。 對於使用計時器的方式,您需要將self.trip
保留self.trip
托管對象,此時save()
會使用Realm文件中的相同ID更新Trip
實例。 為此,您需要使用Realm.create(_:value:update:)
而不是Realm.add(_:update:)
,因為create
不會像add
那樣將非托管實例轉換為托管實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.