【发布时间】:2021-05-15 05:35:50
【问题描述】:
我正在尝试在后台线程中对 Realm Results 实例进行排序。但我得到“从不正确的线程访问领域。”异常。我在这里做错了什么?。
我正在使用这个函数来过滤和更新表格,并随着搜索栏文本字段中的文本的变化而更新表格。
提前致谢。
var previousSearchWork?
func getInvoicesFor(searchedTerm: String, completion: @escaping ([Invoice]) -> Void) {
previousSearchWork?.cancel()
let newSearchWork = DispatchWorkItem {
guard let realm = try? Realm() else { return }
var filteredInvoices = [Invoice]()
if searchedTerm.first!.isLetter { // searching by customer name
let predicate = NSPredicate(format: "name BEGINSWITH[cd] %@ || name CONTAINS[cd] %@", searchedTerm, searchedTerm)
let invoices = realm.objects(Invoice.self).filter(predicate)
filteredInvoices = invoices.sorted {
$0.name!.levenshteinDistance(searchedTerm) < $1.name!.levenshteinDistance(searchedTerm)
}
} else { // searching by id
// ...
}
completion(filteredInvoices)
}
previousSearchWork = newSearchWork
DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + .milliseconds(30), execute: newSearchWork)
}
【问题讨论】:
-
@West1 我故意在后台线程上运行 newSearchWork 导致该函数执行一些耗时的任务。我不希望我的 ui 每次调用该函数时都没有响应。感谢您的回复:)
-
任何时候在 objc Realm 对象上应用 Swift 过滤器时,这些对象都会从 Realm 中“断开”并且不再实时更新 Realm 对象。所以这个
.sorted { $0.name!可能是导致问题的原因。使用 Realm 排序对发票进行排序,而不是快速排序。此外,您似乎正在搜索用户输入的字符串; CONTAINS 搜索整个字符串,包括字符串的第一部分,BEGINSWITH 也搜索字符串的第一部分。你两个都需要吗?此外,该领域位于后台线程上,因此对象位于该线程上;[Invoice]完成后会发生什么? -
@Jay "Realm 在后台线程上,所以对象在那个线程上;完成后 [Invoice] 会发生什么?"这就是导致异常的原因。即使我在后台线程中获取它们,我也尝试在主线程上阅读它们。我已经解决了这个问题。非常感谢你。
-
@Jay。我不能使用领域排序,因为它们不能满足我的需要。例如,我通过将它们的 levenshteinDistance 与搜索的字符串进行比较来进行排序。
-
明白。然而,重要的部分是使用 Swift 对它们进行排序将它们与 Realm 断开连接,它们将不再能够在通知中使用,并且不会实时更新 Realm 对象。很高兴你解决了这个问题。也许您可以发布编码解决方案以帮助未来的读者。