swift 在主线程中使用的后台线程中的领域插入数组
swift realm insert array in background thread use in main
我有一个通过 rest 响应接收到的对象数组,我想将其插入到 background 线程中的领域数据库中,并在 main 中的 uicollectionview 中使用 线程。
一旦收到 rest 的响应,我就会调用回调函数并在后台线程中将数组插入 db。
当我尝试在后台插入对象的主线程 属性 中访问时出现异常( 见下文 ),我认为这是因为对象尚未插入
Terminating app due to uncaught exception 'RLMException', reason:
'Realm accessed from incorrect thread.
模特
class User : Object, Mappable {
dynamic var firstName: String?
dynamic var lastName: String?
required convenience init?(map: Map){
self.init()
}
func mapping(map: Map) {
firstName <- map["firstName"]
lastName <- map["lastName"]
}
}
正在后台线程中插入...
DispatchQueue.global().async {
let realm = try! Realm()
try! realm.write {
realm.add(users)
}
}
渲染在 UI...
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! UserViewCell
let user = users[indexPath.row]
cell.firstName.text = user.firstName
cell.lastName.text = user.lastName
}
请注意,访问 firstName 或 lastName 时会发生异常。
请让我知道我做错了什么
最简单的解决方案是在主线程上创建对 Realm 实例的新引用,并使用新创建的引用从领域中获取所有用户,这样您就可以从同一个线程访问领域。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! UserViewCell
let users = try! Realm().objects(User.self)
let user = users[indexPath.row]
cell.firstName.text = user.firstName
cell.lastName.text = user.lastName
}
另一种解决方案是使用ThreadSafeReference
对象将users
数组从后台线程传递到主线程。但是,如果 users
的类型是 Results
或 List
,您只能为 users
的集合创建一个 ThreadSafeReference
。如果类型为 Results<User>
.
,请参见下面的代码假设 users
var usersRef: ThreadSafeReference<Results<User>>?
DispatchQueue.global().async {
autoreleasepool{
let realm = try! Realm()
try! realm.write {
realm.add(users)
}
usersRef = ThreadSafeReference(to: users)
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! UserViewCell
let realm = try! Realm()
guard let usersRef = usersRef, let users = realm.resolve(usersRef) else {return}
let user = users[indexPath.row]
cell.firstName.text = user.firstName
cell.lastName.text = user.lastName
}
我有一个通过 rest 响应接收到的对象数组,我想将其插入到 background 线程中的领域数据库中,并在 main 中的 uicollectionview 中使用 线程。 一旦收到 rest 的响应,我就会调用回调函数并在后台线程中将数组插入 db。 当我尝试在后台插入对象的主线程 属性 中访问时出现异常( 见下文 ),我认为这是因为对象尚未插入
Terminating app due to uncaught exception 'RLMException', reason: 'Realm accessed from incorrect thread.
模特
class User : Object, Mappable {
dynamic var firstName: String?
dynamic var lastName: String?
required convenience init?(map: Map){
self.init()
}
func mapping(map: Map) {
firstName <- map["firstName"]
lastName <- map["lastName"]
}
}
正在后台线程中插入...
DispatchQueue.global().async {
let realm = try! Realm()
try! realm.write {
realm.add(users)
}
}
渲染在 UI...
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! UserViewCell
let user = users[indexPath.row]
cell.firstName.text = user.firstName
cell.lastName.text = user.lastName
}
请注意,访问 firstName 或 lastName 时会发生异常。
请让我知道我做错了什么
最简单的解决方案是在主线程上创建对 Realm 实例的新引用,并使用新创建的引用从领域中获取所有用户,这样您就可以从同一个线程访问领域。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! UserViewCell
let users = try! Realm().objects(User.self)
let user = users[indexPath.row]
cell.firstName.text = user.firstName
cell.lastName.text = user.lastName
}
另一种解决方案是使用ThreadSafeReference
对象将users
数组从后台线程传递到主线程。但是,如果 users
的类型是 Results
或 List
,您只能为 users
的集合创建一个 ThreadSafeReference
。如果类型为 Results<User>
.
users
var usersRef: ThreadSafeReference<Results<User>>?
DispatchQueue.global().async {
autoreleasepool{
let realm = try! Realm()
try! realm.write {
realm.add(users)
}
usersRef = ThreadSafeReference(to: users)
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! UserViewCell
let realm = try! Realm()
guard let usersRef = usersRef, let users = realm.resolve(usersRef) else {return}
let user = users[indexPath.row]
cell.firstName.text = user.firstName
cell.lastName.text = user.lastName
}