大型的uitableview(1000行)在reloadData()时会冻结。

8 浏览
0 Comments

大型的uitableview(1000行)在reloadData()时会冻结。

我有一个包含大约1000行的UITableView。我还有一个每6秒运行一次的定时器,从网络服务获取数据。每次调用reloadData()都会出现一个闪烁 - 我的应用程序会在短暂的一刻内明显地冻结。在滚动时尤为明显。

我尝试只获取大约400行,闪烁就消失了。有什么方法可以在获取1000行的情况下摆脱这个问题吗?

var items: [Item] = []

Timer.scheduledTimer(withTimeInterval: 6, repeats: true) { [weak self] _ in

guard let strongSelf = self else { return }

Alamofire.request(urlString, method: method, parameters: params) { response in

// 在这里解析响应并将其保存在名为itemsFromResponse的数组中

OperationQueue.main.addOperation {

strongSelf.items = itemsFromResponse

strongSelf.itemsTableView.reloadData()

}

}

}

UITableViewDataSource 代码:

extension ItemViewController: UITableViewDataSource, UITableViewDelegate {

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return items.count

}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath)

cell.textLabel?.text = items[indexPath.row].name

return cell

}

}

0
0 Comments

问题的原因是在更新表格视图时,你是从相同的 OperationQueue 中存储响应的项目并进行更新,这意味着当你的数组正在更新时,UI 线程被阻塞。使用 OperationQueue 本身并不是一种优化任务调度的最佳方式,除非你需要对任务进行细粒度控制(例如取消和高级调度,但在这里你不需要)。相反,你应该使用 DispatchQueue,更多信息请参见这里。

要解决这个问题,你应该在后台完成处理程序中更新数组,然后更新表格。

Timer.scheduledTimer(withTimeInterval: 6, repeats: true) { [weak self] _ in

guard let strongSelf = self else { return }

Alamofire.request(urlString, method: method, parameters: params) { response in

// 解析响应并将其保存在名为 itemsFromResponse 的数组中

strongSelf.items = itemsFromResponse

// 在主(UI)线程上更新表格

DispatchQueue.main.async {

strongSelf.itemsTableView.reloadData()

}

}

}

另外,你也可以考虑一种更高效的获取新数据的方法,因为每隔 6 秒重新加载整个数据集对用户手机的数据和 CPU 来说并不是很高效。

0
0 Comments

问题的原因是每6秒都在重新加载数据,如果数据很大,每6秒都会重新加载1000行数据。解决方法是请求数据并比较是否有新数据,如果有新数据则重新加载数据,否则只需刷新一次。可以使用定时器来定时请求数据,比较并重新加载数据。具体代码如下:

var items: [Item] = []

Timer.scheduledTimer(withTimeInterval: 6, repeats: true) { [weak self] _ in

guard let strongSelf = self else { return }

Alamofire.request(urlString, method: method, parameters: params) { response in

// 在这里解析响应并保存在名为itemsFromResponse的数组中

OperationQueue.main.addOperation {

if(strongSelf.items != itemsFromResponse){

strongSelf.items = itemsFromResponse

strongSelf.itemsTableView.reloadData()

}

}

}

}

这样,每6秒会请求一次数据,如果新数据与已有数据不同,则更新数据并重新加载表格视图。这样可以避免每次都重新加载所有1000行数据,提高性能。

0