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 的类型是 ResultsList,您只能为 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
}