Swift - UICollectionView reloadItems 需要太长时间

Posted

技术标签:

【中文标题】Swift - UICollectionView reloadItems 需要太长时间【英文标题】:Swift - UICollectionView reloadItems takes too long 【发布时间】:2017-10-25 03:52:56 【问题描述】:

在用户选择联系人(method didSelect contact) 后,我只想重新加载单个单元格。如果单元格中的项目数越来越大,则该过程会变慢。我也尝试在DispatchQueue.main.async code 中实现,仍然需要一些时间来加载。

cellForItemAt 和 noOfItemInSection (AddCell) - 总单元格 4

var indexPaths = [IndexPath]()

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
   indexPaths.append(indexPath)

   if indexPath.item == 1 
        let addCell = collectionView.dequeueReusableCell(withReuseIdentifier: CellId, for: indexPath) as! AddCell
        addCell.btnAdd.addTarget(self, action: #selector(handleOpenContact), for: .touchUpInside)
        addCell.invitees = invitees
        return addCell
    


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 4
    

cellForItemAt 和 noOfItemInSection (SubAddCell)

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: subAddId, for: indexPath) as! SubAddCell
        cell.delegate = self
        cell.invitee = invitees[indexPath.item]
        return cell
    

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return invitees.count
    

didSelect (ContactPicker)

func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) 
        let invitee = Invitee()
        invitee.name = contact.givenName

        if contact.isKeyAvailable(CNContactPhoneNumbersKey) 
            for phoneNumber: CNLabeledValue in contact.phoneNumbers 
                let a = phoneNumber.value
                print("\(a.stringValue)")
                invitee.phoneNo = a.stringValue
            
        
        self.invitees.append(invitee)

        for index in self.indexPaths 
            if index == [0, 0] 
                print(index)
                self.collectionView?.reloadItems(at: [index])
            
        
    

我在cellForItemAt 方法中获得了indexPaths 的值。如果被邀请者包含 5 个项目,print(index) 将打印 19 个值。我不知道为什么。下面是图片。

用户界面设计

如何优化reloadItems?

非常感谢任何帮助。非常感谢。

【问题讨论】:

您能描述一下您的cellForItemAtIndexPath 方法的其余部分吗?您只显示您处理索引 1 处的单元格......而您显然使用了 19 个单元格。剩下的方法是什么? @murphguy,它只有 4 个单元格。对于那个特定的单元格,里面有一个UICollectionView。我已经更新了问题。 这就是你的挑战。可折叠单元格动画/处理相当繁重。所以这取决于:你是否在单元格内使用自动布局?单元格的内容是动态的吗?您是否通过单独的线程异步加载图像?这三个问题应该可以回答您的应用为何滞后的问题。 【参考方案1】:

我认为你在cellForItemAt 中有这个indexPaths.append(indexPath),所以为什么重新加载数据后 indexPaths 会增加。您可以使用 NSSet 而不是 NSArray 来确保您的对象是唯一的。

有了这个:cell.invitee = invitees[indexPath.item],你是否为invitee 实现了 didSet? 如果你这样做了,我认为需要先在后台队列中准备数据。例如

DispatchQueue(label: "queue").async 
  let image = <# process image here #>
  let name = <# process name here #>
  DispatchQueue.main.async 
    self.imageView.image = image
    self.label.text = name
  

希望我的建议能帮到你!

【讨论】:

我确实为 invitee 实现了 didSet。 NSSet 需要设置为 IndexPath 吗?我没找到你。 -我猜您的didSet 需要花费大量时间来处理数据以填充到您的 UI 元素中。 - 并且 NSSet 确保你的 indexPaths 没有重复!【参考方案2】:

Collectionviewsios 中最强大的 UI 工具,但如果做错了,或者如果被滥用(发生这种情况,不用担心),它们可能会对您的 UX 造成更糟的影响。 .要查看这些东西是如何受到影响的,请阅读 XCode 工具以及如何使用它们来调试您的 UI 性能。

需要考虑的重要提示:

逐帧操作(即加载您的collectionviewcell、展开或未展开)执行平滑滚动的时间不应超过17 毫秒。

UICollectionView performance - _updateVisibleCellsNow

因此,您需要使您的细胞尽可能简单和高效。这是最好的起点,尤其是当您的可扩展单元格本身包含复杂的子视图(如 collectionviews)时。

【讨论】:

以上是关于Swift - UICollectionView reloadItems 需要太长时间的主要内容,如果未能解决你的问题,请参考以下文章

Swift:滚动时 UICollectionView 标题消失

swift UICollectionView + RxReachedBottom.swift

如何将 UIPageControl 连接到 UICollectionView (Swift)

Swift 4 UICollectionView 检测滚动结束

如何使用 swift 重置 UICollectionView 滚动位置?

Swift 3 - 带有填充的 UICollectionView 中心单元