如何在不阻止用户交互的情况下执行tableView.reloadData()

时间:2019-01-27 14:09:32

标签: ios swift

我使用searchBar搜索产品列表并在tableView中显示结果,我希望每个角色都可以开始新的搜索旅程,我已经通过某种异步队列完成了在全球范围内搜索产品列表的工作在500毫秒后排队并在mainQueue中更新tableView。

问题在于,在重新加载表视图时,用户交互块会阻塞,并且用户无法在表视图完成之前输入新字符

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(searchOnProducts), object: nil)
    self.searchKeyWord = searchText
    self.perform(#selector(searchOnProducts), with: nil, afterDelay: 0.0)
}

@objc func searchOnProducts() {
    DispatchQueue.global().async {
        let returnedProducts = DataHolder.getProductsWithSearch(self.searchKeyWord)
        let productsRef: ThreadSafeReference<Results<Product>>?
        if returnedProducts != nil && returnedProducts!.count != self.searchProducts.count {
            productsRef = ThreadSafeReference(to: returnedProducts!)
        } else if returnedProducts == nil && self.searchProducts.count != 0 {
           productsRef = nil
        } else {
            return
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500), execute: {
            if productsRef != nil {
                let realm = try! Realm()
                guard let products = realm.resolve(productsRef!) else {
                    return
                }
                self.searchProducts = Array(products)
            } else {
                self.searchProducts.removeAll()
            }
            self.searchTV.reloadData()
        })
    }
}

1 个答案:

答案 0 :(得分:0)

您正在主线程上的RealmDB上进行工作。您可能还应该将其移至全局队列。然后仅在主线程上调用reloadData()

编辑:在cellForRow中,您还应该访问全局队列中的结果数组,然后更新主线程上的单元格内容。这样,您应该应该能够避免收到的线程错误。

另外: 您是否尝试过配置您的应用?那应该使您更好地了解哪些代码行需要花费很长时间。创建表视图单元格时,您是否还有其他耗时的事情?