UITableView 滚动性能问题

Posted

技术标签:

【中文标题】UITableView 滚动性能问题【英文标题】:UITableView scrolling performance problem 【发布时间】:2021-12-31 12:23:12 【问题描述】:

我目前是一名 5 个月的初级 ios 开发人员。

我正在进行的项目是一个应用程序,它通过 websocket 连接实时显示 70 种加密货币的价格。

我们在开发应用程序时使用了 websocket 连接、UItableview、UITableViewDiffableDataSource、NSDiffableDataSourceSnapshot。

但是现在由于同时处理的数据太多,在tableview中滚动时出现了滚动速度变慢或不停止滚动和UI锁定等问题。

在我使用计时器分析器检查 cpu 性能后,我得出的结论是 updateDataSource 和 updateUI 函数耗尽了主线程。

func updateDataSource(model: [PairModel]) 
    var snapshot = DiffableDataSourceSnapshot()
    let diff = model.difference(from: snapshot.itemIdentifiers)
    let currentIdentifiers = snapshot.itemIdentifiers
    
    guard let newIdentifiers = currentIdentifiers.applying(diff) else 
            return
        
    snapshot.appendSections([.first])
    snapshot.deleteItems(currentIdentifiers)
    snapshot.appendItems(newIdentifiers)
    
    dataSource?.apply(snapshot, animatingDifferences: false, completion: nil)


func updateUI(data: SocketData) 
    
    guard let newData = data.data else  return 
    guard let current = data.data?.price else  return 
    guard let closed = data.data?.lastDayClosePrice else  return 
    
    let dailyChange = ((current - closed)/closed)*100
    
    DispatchQueue.main.async  [self] in
        
        if model.filter( $0.symbol == newData.pairSymbol ).first != nil 
            let index = model.enumerated().first(where:  $0.element.symbol == newData.pairSymbol)
            guard let location = index?.offset else  return 
            model[location].price = current
            model[location].dailyPercent = dailyChange
            
            if calculateLastSignalTime(alertDate: model[location].alertDate) > 0 
                //Do Nothing
             else 
                model[location].alertDate = ""
                model[location].alertType = ""
            
            
            if let text = allSymbolsView.searchTextField.text 
                if text != "" 
                    filteredModel = model.filter( $0.name.contains(text) || $0.symbol.contains(text) )
                    updateDataSource(model: filteredModel)
                 else 
                    filteredModel = model
                    updateDataSource(model: filteredModel)
                
            
        
        delegate?.pricesChange(data: self.model)
    

问候。

【问题讨论】:

尝试仅使用主队列进行 ui 更新。如果您更新模型,则无需在主队列中完成。 感谢您的建议,我已经尝试过了,但仍然没有 %100 有效。滚动有时没有响应 可以做一个小优化;如果让 location = modelFirstIndex(where ...) 。这样可以避免在过滤后的模型版本中进行过滤、枚举和查找。 【参考方案1】:

您的所有代码都在主线程上运行。您必须将整个updateUI 函数包装在DispatchQueue.global(qos:) 中,然后将dataSource.apply(snapshot) 行包装在DispatchQueue.main.async 中。 dataSource.apply(snapshot) 行是您在发布的所有代码中所做的唯一 UI 工作。

【讨论】:

以上是关于UITableView 滚动性能问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS5:UITableView 滚动性能不佳

UITableView 滚动性能

使用内联选择器的 UITableView 滚动性能

自 iOS 9 以来 UITableView 的滚动性能不佳(之前效果很好)

如何提高 UITableVIew 的性能?

UITableView滚动性能优化