ios – 滚动双向滚动UICollectionView并具有大量单元格(250,000或更多)时可见延迟

ios – 滚动双向滚动UICollectionView并具有大量单元格(250,000或更多)时可见延迟,第1张

概述我是UICollectionViewFlowLayout的子类,以便在UICollectionView中进行双向滚动.对于较少数量的行和节数(100-200行和节),滚动工作正常,但是当我在UICollectionView中增加行和节数超过500,即250,000或更多单元格时,滚动时存在明显的滞后.我已经在layoutAttributesForElementsInRect中跟踪了for循环的源代 我是UICollectionVIEwFlowLayout的子类,以便在UICollectionVIEw中进行双向滚动.对于较少数量的行和节数(100-200行和节),滚动工作正常,但是当我在UICollectionVIEw中增加行和节数超过500,即250,000或更多单元格时,滚动时存在明显的滞后.我已经在layoutAttributesForElementsInRect中跟踪了for循环的源代码.我使用Dictionary来保存每个单元格的UICollectionVIEwLayoutAttributes以避免重新计算它并循环遍历它以从layoutAttributesForElementsInRect返回单元格的属性
import UIKitclass LuckGameCollectionVIEwLayout: UICollectionVIEwFlowLayout {    // Used for calculating each cells CGRect on screen.    // CGRect will define the Origin and Size of the cell.    let CELL_HEIGHT = 70.0    let CELL_WIDTH = 70.0    // Dictionary to hold the UICollectionVIEwLayoutAttributes for    // each cell. The layout attribtues will define the cell's size    // and position (x,y,and z index). I have found this process    // to be one of the heavIEr parts of the layout. I recommend    // holding onto this data after it has been calculated in either    // a dictionary or data store of some kind for a smooth performance.    var cellAttrsDictionary = Dictionary<NSIndexPath,UICollectionVIEwLayoutAttributes>()    // defines the size of the area the user can move around in    // within the collection vIEw.    var contentSize = CGSize.zero    overrIDe func collectionVIEwContentSize() -> CGSize {        return self.contentSize    }    overrIDe func prepareLayout() {        // Cycle through each section of the data source.        if collectionVIEw?.numberOfSections() > 0 {            for section in 0...collectionVIEw!.numberOfSections()-1 {                // Cycle through each item in the section.                if collectionVIEw?.numberOfItemsInSection(section) > 0 {                    for item in 0...collectionVIEw!.numberOfItemsInSection(section)-1 {                        // Build the UICollectionVIELayoutAttributes for the cell.                        let cellindex = NSIndexPath(forItem: item,inSection: section)                        let xPos = Double(item) * CELL_WIDTH                        let yPos = Double(section) * CELL_HEIGHT                        let cellAttributes = UICollectionVIEwLayoutAttributes(forCellWithIndexPath: cellindex)                        cellAttributes.frame = CGRect(x: xPos,y: yPos,wIDth: CELL_WIDTH,height: CELL_HEIGHT)                        // Save the attributes.                        cellAttrsDictionary[cellindex] = cellAttributes                    }                }            }        }        // Update content size.        let contentWIDth = Double(collectionVIEw!.numberOfItemsInSection(0)) * CELL_WIDTH        let contentHeight = Double(collectionVIEw!.numberOfSections()) * CELL_HEIGHT        self.contentSize = CGSize(wIDth: contentWIDth,height: contentHeight)    }    overrIDe func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionVIEwLayoutAttributes]? {        // Create an array to hold all elements found in our current vIEw.        var attributesInRect = [UICollectionVIEwLayoutAttributes]()        // Check each element to see if it should be returned.        for (_,cellAttributes) in cellAttrsDictionary {            if CGRectIntersectsRect(rect,cellAttributes.frame) {                attributesInRect.append(cellAttributes)            }        }        // Return List of elements.        return attributesInRect    }    overrIDe func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionVIEwLayoutAttributes? {        return cellAttrsDictionary[indexPath]!    }    overrIDe func shouldInvalIDateLayoutForBoundsChange(newBounds: CGRect) -> Bool {        return false    }}

编辑:
以下是我在layoutAttributesForElementsInRect方法中提出的更改.

overrIDe func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionVIEwLayoutAttributes]? {            // Create an array to hold all elements found in our current vIEw.    var attributesInRect = [UICollectionVIEwLayoutAttributes]()    let xOffSet = self.collectionVIEw?.contentOffset.x    let yOffSet = self.collectionVIEw?.contentOffset.y    let totalColumnCount = self.collectionVIEw?.numberOfSections()    let totalRowCount = self.collectionVIEw?.numberOfItemsInSection(0)    let startRow = Int(Double(xOffSet!)/CELL_WIDTH) - 10    //include 10 rows towards left    let endRow = Int(Double(xOffSet!)/CELL_WIDTH + Double(Utils.getScreenWIDth())/CELL_WIDTH) + 10 //include 10 rows towards right    let startCol = Int(Double(yOffSet!)/CELL_HEIGHT) - 10 //include 10 rows towards top    let endCol = Int(Double(yOffSet!)/CELL_HEIGHT + Double(Utils.getScreenHeight())/CELL_HEIGHT) + 10 //include 10 rows towards bottom    for(var i = startRow ; i <= endRow; i = i + 1){        for (var j = startCol ; j <= endCol; j = j + 1){            if (i < 0 || i > (totalRowCount! - 1) || j < 0 || j > (totalColumnCount! - 1)){                continue            }            let indexPath: NSIndexPath = NSIndexPath(forRow: i,inSection: j)            attributesInRect.append(cellAttrsDictionary[indexPath]!)        }    }    // Return List of elements.    return attributesInRect}

我已经计算了collectionVIEw的偏移量,并用它来计算屏幕上可见的单元格(使用每个单元格的高度/宽度).我不得不在每一侧添加额外的单元格,以便当用户滚动时没有丢失的单元格.我测试了这个并且性能很好.

解决方法 通过利用已知单元格大小的layoutAttributesForElementsInRect(rect:CGRect),您不需要缓存属性,只需在collectionVIEw请求它们时为给定的rect计算它们.您仍然需要检查0的边界情况和最大的部分/行计数,以避免计算不需要的或无效的属性,但可以在循环周围的where子句中轻松完成.这是一个工作示例,我已经测试了1000个部分x 1000行,它工作得很好,没有滞后于设备:

编辑:我添加了更大的Result,以便在滚动到达之前可以预先计算属性.从您的编辑看起来,您仍然在缓存我认为性能不需要的属性.此外,它会带来更大的内存占用,滚动更多.还有一个原因是你不想从回调中使用提供的CGRect而不是从contentOffset手动计算一个?

class LuckGameCollectionVIEwLayout: UICollectionVIEwFlowLayout {let CELL_HEIGHT = 50.0let CELL_WIDTH = 50.0overrIDe func collectionVIEwContentSize() -> CGSize {    let contentWIDth = Double(collectionVIEw!.numberOfItemsInSection(0)) * CELL_WIDTH    let contentHeight = Double(collectionVIEw!.numberOfSections()) * CELL_HEIGHT    return CGSize(wIDth: contentWIDth,height: contentHeight)}overrIDe func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionVIEwLayoutAttributes]? {    let biggerRect = rect.insetBy(dx: -2048,dy: -2048)    let startIndexY = Int(Double(biggerRect.origin.y) / CELL_HEIGHT)    let startIndexX = Int(Double(biggerRect.origin.x) / CELL_WIDTH)    let numberOfVisibleCellsInRectY = Int(Double(biggerRect.height) / CELL_HEIGHT) + startIndexY    let numberOfVisibleCellsInRectX = Int(Double(biggerRect.wIDth) / CELL_WIDTH) + startIndexX    var attributes: [UICollectionVIEwLayoutAttributes] = []    for section in startIndexY..<numberOfVisibleCellsInRectY        where section >= 0 && section < self.collectionVIEw!.numberOfSections() {            for item in startIndexX..<numberOfVisibleCellsInRectX                where item >= 0 && item < self.collectionVIEw!.numberOfItemsInSection(section) {                    let cellindex = NSIndexPath(forItem: item,inSection: section)                    if let attrs = self.layoutAttributesForItemAtIndexPath(cellindex) {                        attributes.append(attrs)                    }            }    }    return attributes}overrIDe func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionVIEwLayoutAttributes? {    let xPos = Double(indexPath.row) * CELL_WIDTH    let yPos = Double(indexPath.section) * CELL_HEIGHT    let cellAttributes = UICollectionVIEwLayoutAttributes(forCellWithIndexPath: indexPath)    cellAttributes.frame = CGRect(x: xPos,height: CELL_HEIGHT)    return cellAttributes}}
总结

以上是内存溢出为你收集整理的ios – 滚动双向滚动UICollectionView并具有大量单元格(250,000或更多)时可见延迟全部内容,希望文章能够帮你解决ios – 滚动双向滚动UICollectionView并具有大量单元格(250,000或更多)时可见延迟所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1103800.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-28
下一篇2022-05-28

发表评论

登录后才能评论

评论列表(0条)

    保存