ios - 在 Collection View 中异步追加项目失败

标签 ios uicollectionview

我正在使用 Alamofire 构建类似 pinterest 的布局。

然后我关注了uicollectionview-custom-layout-tutorial-pinterest在这里建立一个类似 pinterest 的布局。当我想用异步下载的照片实现它时,它失败了。

Assertion failure in -[UICollectionViewData layoutAttributesForItemAtIndexPath:]

Alamofire.request(Unicooo.Router.ReadPostList("",["act_id": self.actId, "page": self.currentPage])).validate().responseJSON {
            response in
            switch response.result {
            case .Success:
                let JSON = response.result.value
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
                    let photoInfos =  ((JSON as! NSDictionary).valueForKey("results") as! [NSDictionary]).map {
                        PostPhotoInfo(id: ($0["id"] as! Int), title: ($0["post_title"] as! String)...)
                    }

                    let lastItem = self.postPhotos.count
                    self.postPhotos.addObjectsFromArray(photoInfos)
                    let indexPaths = (lastItem..<self.postPhotos.count).map { NSIndexPath(forItem: $0, inSection: 0)}
                    dispatch_async(dispatch_get_main_queue()) {
                        self.collectionView!.insertItemsAtIndexPaths(indexPaths) // Thread 1: breakpoint 1.1.
                    }
                }

当我将 Main.storyboard Collection View 布局设置为 Flow 时效果很好,但是当我像这样使用自定义流时:

private var cache = Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>()  //I change cache to Dictionary
override func prepareLayout() {
        if cache.isEmpty {
            let columnWidth = contentWidth / CGFloat(numberOfColumns)
            var xOffset = [CGFloat]()
            for column in 0 ..< numberOfColumns {
                xOffset.append(CGFloat(column) * columnWidth )
            }
            var column = 0
            var yOffset = [CGFloat](count: numberOfColumns, repeatedValue: 0)

            for item in 0 ..< collectionView!.numberOfItemsInSection(0) {

                let indexPath = NSIndexPath(forItem: item, inSection: 0)

                let width = columnWidth - cellPadding * 2
                let photoHeight = delegate.collectionView(collectionView!, heightForPhotoAtIndexPath: indexPath,
                    withWidth:width)
                let annotationHeight = delegate.collectionView(collectionView!,
                    heightForAnnotationAtIndexPath: indexPath, withWidth: width)
                let height = cellPadding +  photoHeight + annotationHeight + cellPadding

                let frame = CGRect(x: xOffset[column], y: yOffset[column], width: columnWidth, height: height)
                insetFrame = CGRectInset(frame, cellPadding, cellPadding)

                let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
                attributes.frame = insetFrame!
                cache[indexPath] = attributes  //I change this line

                contentHeight = max(contentHeight, CGRectGetMaxY(frame))
                yOffset[column] = yOffset[column] + height

                column = column >= (numberOfColumns - 1) ? 0 : ++column
            }
        }
    }

    override func collectionViewContentSize() -> CGSize {
        return CGSize(width: contentWidth, height: contentHeight)
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

        var layoutAttributes = [UICollectionViewLayoutAttributes]()

        for (_, attributes) in cache {
            if CGRectIntersectsRect(attributes.frame, rect) {
                layoutAttributes.append(attributes)
            }
        }
        return layoutAttributes
    }

当我在 google 中搜索有关 Collection View 的所有内容时:我尝试添加此方法:

override func layoutAttributesForItemAtIndexPath(_ indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {

        let attributes = cache[indexPath]
        return attributes
    }

但是还是不行。我想这可能与layoutAttributesForItemAtIndexPath没有返回更正属性有关。

感谢您的任何想法。

最佳答案

有点晚了,但我遇到了同样的问题。 您还需要覆盖 invalidateLayout 方法。

override func invalidateLayout() {
    cache.removeAll()
    super.invalidateLayout()
}

然后您需要在调用 insertItemsAtIndexPaths 之前调用 invalidateLayout 方法

您需要清除缓存,因为只有在缓存为空时才会调用 prepareLayout 方法中的逻辑。由于布局已经准备好并且缓存已填充,因此不会计算新的布局属性并将其存储在缓存中。

关于ios - 在 Collection View 中异步追加项目失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35932706/

相关文章:

ios - iOS 中的谷歌页面排名

ios - CloudKit-不会更新 (Swift)

ios - 模拟器未运行时,xcrun simctl boot/uninstall 挂起

ios - 自定义单元格类中的 init() 是 collectionView 的委托(delegate)和数据源

iphone/ipad - 使用 Autoresize 和 addSubview 时出现问题

ios - 如何将 UICollectionViewCell 置于最前面?

ios - CollectionView 单元格在滚动后更改大小 - AutoLayout

ios - 需要显示所有项目,连续显示一个项目

swift - 使用 UIImagePicker 选取图像后重新加载 UICollectionView 的正确时机和位置

ios - 尝试使用 CocoaPods 0.38 关闭 MagicalRecord 登录时出错