我有一个Store
,Area
表,在调用api后获取Store
Area
数据,然后会创建Store
,Area
表;
目标:对于渲染ui,我需要Store
areaName
。从db获取存储,然后使用areaName
组合到存储,然后在后台线程中根据areaName
组成一个二维数组。然后传递2d数组以在主线程中呈现ui
实施:
在后台线程中读取Store,使用areaCode获取Area,然后获取areaName,然后store.areaName = area.areaName
获取组合Store,并使用ThreadSafeReference
获取商店的引用
在主线程中使用realm.resolve
来获取主线程中的商店,但只能得到store.address
值,无法获得store.areaName
class Store: Object {
dynamic var storeCode: String = ""
dynamic var areaCode: String = ""
dynamic var address: String = ""
dynamic var phone: String = ""
var areaName: String = ""
var userId: Int = 0
}
class Area: Object {
dynamic var areaCode: String = ""
dynamic var areaName: String = ""
}
//// in background thread//////
let realmInBack = try! Realm()
let stores = getStore(by userId: Int) // here get a list of stores from db
stores.forEach{ (store) in
let area = getArea(by areaCode: String) // get area
let areaName = area.areaName // get the areaName from area
store.areaName = areaName // assign areaName to store
let storeRef = ThreadSafeReference(to: store) // get the storeRef
}
//// in main thread /////
let realm = try! Realm()
let storeInMain = realm.resolve(storeRef)
// then use storeInMain to render ui
请列出通过线程传递realm对象的方法吗? 我目前知道以下方法: 1. ThreadSafeReference(在我的情况下失败) 2.自己将领域对象转换为普通类
答案 0 :(得分:0)
对于这个简单的情况,您实际上并不需要使用ThreadSafeReference
对象。您应该只将对象的属性保存到可用于标识该特定对象的变量(如果您使用primaryKey
s,则优选为primaryKey
),然后使用Realm中的主键检索对象在主线上。
var storeCodeRef = "" //make sure this variable is accessible in the scope of where your code on the main thread is called from as well
let realmInBack = try! Realm()
let stores = getStore(by userId: Int) // here get a list of stores from db
stores.forEach{ (store) in
let area = getArea(by areaCode: String) // get area
let areaName = area.areaName // get the areaName from area
store.areaName = areaName // assign areaName to store
//save the unique identifier for the store
storeCodeRef = store.storeCode
}
//// in main thread /////
let realm = try! Realm()
let store = realm.object(ofType: Store.self).filter("storeCode == %@",storeCodeRef).first //assuming storeCodes are unique
如果您使用的是主键,则可以使用
let store = realm.object(ofType: Store.self, forPrimaryKey: storeCodeRef)
由于您在主线程上声明了对Realm实例的新引用并从该引用访问Store
对象,因此您不会收到任何错误。
根据评论更新:
您的Class
模型存在缺陷。您希望在Realm中保留的所有属性都需要使用dynamic
关键字声明,否则无法将它们动态分派到Realm使用的Obj-C运行时。
class Store: Object {
dynamic var storeCode: String = ""
dynamic var areaCode: String = ""
dynamic var address: String = ""
dynamic var phone: String = ""
dynamic var areaName: String = ""
dynamic var userId: Int = 0
}
其次,如果要修改实际的Store对象,为什么要将ThreadSafeReference
存储到各个商店,您可以在写入事务中执行此操作并将ThreadSafeReference
存储到Results
1}}实例,因此您只需要解析单个引用,而不是每个单独的Store。
以下代码已经过测试,正在Realm游乐场工作。
class Store: Object {
dynamic var storeCode: String = ""
dynamic var address: String = ""
dynamic var phone: String = ""
dynamic var userId: Int = 0
dynamic var areaCode: String = ""
dynamic var areaName: String = ""
}
class Area: Object {
dynamic var areaCode: String = ""
dynamic var areaName: String = ""
}
try! realm.write {
realm.add([Store(value: ["userId":1,"storeCode":"1"]),Store(value: ["userId":1,"storeCode":"2"]),Store(value: ["userId":2,"storeCode":"1"])])
}
print(realm.objects(Store.self))
//// in some thread//////
var storesRef: ThreadSafeReference<Results<Store>>?
DispatchQueue(label: "background").sync {
autoreleasepool{
let realmInBack = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "TemporaryRealm"))
let stores = realmInBack.objects(Store.self).filter("userId == 1")
print("Stores for user 1:",stores)
try! realmInBack.write {
let area = Area(value: ["areaCode":"a","areaName":"AreaA"])
realmInBack.add(area)
stores.forEach{ (store) in
store.areaCode = area.areaCode
}
}
print("Modified stores:",stores)
storesRef = ThreadSafeReference(to: stores)
}
}
//// in main thread /////
DispatchQueue.main.async {
let mainRealm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "TemporaryRealm"))
guard let storesRef = storesRef, let storeInMain = mainRealm.resolve(storesRef) else {
print("Couldn't resolve stores reference"); return
}
print("Stores from ThreadSafeReference:",storeInMain)
}