在主线程中使用后台线程的快速领域插入数组 [英] swift realm insert array in background thread use in main

查看:64
本文介绍了在主线程中使用后台线程的快速领域插入数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组通过rest响应接收的对象,我想将它们插入背景线程中的realm db中,并在 main 线程的uicollectionview中使用.收到休息的响应后,我将调用回调函数,并将数组插入后台线程中的db中.当我尝试访问在后台插入的对象的主线程属性时出现的问题,我得到了异常(请参见下文),我认为这是由于尚未插入对象而引起的

I have an array of objects received via rest response, which I want to insert into realm db in a background thread and use in a uicollectionview in main thread. As soon as I receive response from rest, I call callback function and insert array into db in a background thread. The problem when I am trying to access in main thread property of object being inserted in background I'm getting exception (see below) which I assume because of object not yet inserted

由于未捕获的异常"RLMException"而终止应用程序,原因:从错误的线程访问了领域.

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)
  }
}

在用户界面中呈现...

Rendering in 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时会发生异常.

Please note that exception occur either on accessing firstName or lastName.

请让我知道我在做什么错

Please let me know what I'm doing wrong here

推荐答案

最简单的解决方案是在主线程上创建对Realm实例的新引用,并使用新创建的引用从领域中获取所有用户.从同一线程访问领域.

The easiest solution is to create a new reference to your Realm instance on the main thread and fetch all users from realm using the newly created reference, so you will be accessing realm from the same thread.

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 ,则只能为您的 users 集合创建单个 ThreadSafeReference List 的列表.如果类型为 Results< User> ,请参见以下假定 users 的代码.

Another solution is to use a ThreadSafeReference object to pass the users array from the background thread to the main thread. However, you can only create a single ThreadSafeReference to your collection of users if the type of users is either Results of List. See below code assuming users if of type Results<User>.

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
}

这篇关于在主线程中使用后台线程的快速领域插入数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆