【问题标题】:TableView cells with collectionView performance issue具有 collectionView 性能问题的 TableView 单元格
【发布时间】:2016-09-12 14:16:42
【问题描述】:

我有以下布局: 当滚动 tableView fps 下降到 25 左右时,它变得非常抖动。

我认为这是我对 collectionView 的实现,因为很多操作都是在 cellForIndexAtPath 中执行的。但是看不出有什么可以优化的?

extension MyTableViewController: UICollectionViewDelegate, UICollectionViewDataSource {

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
    // No sections are longer than 99
    if(collectionView.tag < 100)
    {
        let code = codes0[collectionView.tag].objectForKey("code") as! String

        return code.componentsSeparatedByString(",").count
    }
    else if(collectionView.tag < 200)
    {
        let code = codes1[collectionView.tag-100].objectForKey("code") as! String

        return code.componentsSeparatedByString(",").count
    }
    else
    {
        let code = codes2[collectionView.tag-200].objectForKey("code") as! String

        return code.componentsSeparatedByString(",").count
    }
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("code", forIndexPath: indexPath) as! ImageCodeCollectionViewCell

    // Read that this should help for GPU
    cell.layer.shouldRasterize = true
    cell.layer.rasterizationScale = UIScreen.mainScreen().scale

    var codeLength:String! = ""

    if(collectionView.tag < 100)
    {
        codeLength = self.codes0[collectionView.tag].objectForKey("code") as! String
    }
    else if(collectionView.tag < 200)
    {
        codeLength = self.codes1[collectionView.tag-100].objectForKey("code") as! String
    }
    else
    {
        codeLength = self.codes2[collectionView.tag-200].objectForKey("code") as! String
    }

    let cLength = codeLength.componentsSeparatedByString(",")

    if(indexPath.row <= cLength.count)
    {
        cell.imageCode.image = UIImage(named: cLength[indexPath.row])
    }

    return cell
}

我的 tableView 看起来像:

这里是 collectionView 数据源和委托集

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCellWithIdentifier("cheat") as! CodeTableViewCell

    cell.layer.shouldRasterize = true
    cell.layer.rasterizationScale = UIScreen.mainScreen().scale

    cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row, forSection: indexPath.section)

    return cell
}

func tableView(tableView: UITableView, willDisplayCell cell: CodeTableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
{
    switch indexPath.section
    {
    case 2:
        cell.name = codes2[indexPath.row].objectForKey("name") as! String

        cell.descript = ((codes2[indexPath.row].objectForKey("description") as! String).isEmpty ? "-" : codes2[indexPath.row].objectForKey("description") as! String)

    case 1:
        cell.name = codes1[indexPath.row].objectForKey("name") as! String

        cell.descript = ((codes1[indexPath.row].objectForKey("description") as! String).isEmpty ? "-" : codes1[indexPath.row].objectForKey("description") as! String)

    default:
        cell.name = codes0[indexPath.row].objectForKey("name") as! String

        cell.descript = ((codes0[indexPath.row].objectForKey("description") as! String).isEmpty ? "-" : codes0[indexPath.row].objectForKey("description") as! String)
    }
}

【问题讨论】:

  • 看一眼代码,我认为,这是由于 cellForRow... 方法中的许多检查。

标签: ios swift uicollectionview tableview


【解决方案1】:

通过简要查看您的代码,您似乎可以只使用UICollectionView 设置,将UICollectionReusableView 用作标头。这样,所有collectionViews 将重用相同的cells,并且您不必在每次UITableViewCell 可见时都对collectionViews 进行布局。

您也可以考虑将code.componentsSeparatedByString(",").count 等操作的结果存储在单独的变量中,并且仅在您的数据更改后才计算它。

【讨论】:

  • 是的,我明白,但由于我必须使用 UICollectionReusableView 作为标题,如果我需要将“全局”标题粘贴在导航栏下方,我是否不必创建自定义标题?
  • 我明白了。我必须说,在我第一次看你的设置时,我迷惑了这一点。正如this post 中提到的那样,有很多方法可以将中间标头实现为custom cells。在尝试其他任何事情之前,您是否尝试过将 图像 加载到 后台线程 上?
  • UIImage 以及任何与 UI 相关的东西都必须在主线程上设置吗?因为我没有下载任何东西,只是分配图像,这应该不是问题吗?
  • 你说得对,UI的更新必须在主线程上完成,但是cell.imageCode.image = UIImage(named: cLength[indexPath.row])这行都是加载图像,然后将其分配给细胞。试着评论那部分,看看你是否有任何改进。如果这样做,以下调整可能会有所帮助:dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ let image = UIImage(named: cLength[indexPath.row]) dispatch_async(dispatch_get_main_queue(), ^{ cell.imageCode.image = image }) })
  • 我已经尝试过了,在 iOS 10 上效果很好,但不适用于以下设备?
猜你喜欢
  • 2020-02-14
  • 1970-01-01
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-12
相关资源
最近更新 更多