访问 Realms 对象列表时出错:从不正确的线程访问的领域

Error acessing list of Realm's objects: Realm accessed from incorrect thread

我有兴趣点列表。这些点是从 Realm 数据库 加载的。每个点都应显示其到 用户位置 .

的距离

每次我得到一个新位置,我都会计算到所有点的距离。为了避免屏幕冻结,我在主线程的 table 中显示列表后,在后台线程中进行数学计算。

func updatedLocation(currentLocation: CLLocation) {

    let qualityOfServiceClass = QOS_CLASS_BACKGROUND
    let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
    dispatch_async(backgroundQueue, {
        for point in self.points{
            let stringDistance = self.distanceToPoint(currentLocation, destination: point.coordinate)
            point.stringDistance = stringDistance
        }

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.tableView?.reloadData()
        })
    })
}

但是我得到这个错误:

libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.

我知道我收到此错误是因为我正在后台线程中访问领域对象,但是,它们已经加载到数组中,我从未对数据库进行新查询。 另外,我正在更新的 var 没有保存到数据库中。

知道如何解决这个问题吗?我想避免在主线程中进行数学运算。

提前致谢

我假设您将 Realm Results 对象包装到 Array 中,如下所示:

let results = realm.objects(Point)
self.points = Array(results)

然而,这还不够。因为数组中的每个元素仍然与 Realm 相关联,所以不能访问另一个线程。

推荐的方法是重新创建领域并重新获取每个线程的结果。

dispatch_async(backgroundQueue, {
    let realm = try! Realm()
    let points = realm.objects(...)

    try! realm.write {
        for point in points{
            let stringDistance = self.distanceToPoint(currentLocation, destination: point.coordinate)
            point.stringDistance = stringDistance
        }
    }

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        ...
    })
})

Realm 对象具有实时更新功能。当提交更改为子线程上的 Realm 对象时,这些更改会立即反映到其他线程中的对象。所以你不需要在主线程中重新获取查询。您应该做的只是重新加载 table 视图。

如果您想包装数组并将其直接传递给其他线程,您应该按如下方式包装结果的所有元素:

let results = realm.objects(Point)
self.points = results.map { (point) -> Point in
    return Point(value: point)
}