无法在集合视图中异步附加项目

时间:2016-03-11 05:11:52

标签: ios uicollectionview

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

我跟着uicollectionview-custom-layout-tutorial-pinterest来建立类似pinterest的布局。当我想用异步下载的照片来实现它时,它会失败。

  

断言失败 - [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集合视图布局设置为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中搜索关于集合视图的所有内容时:我尝试添加此方法:

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

        let attributes = cache[indexPath]
        return attributes
    }

但仍然无法工作。我认为这可能与layoutAttributesForItemAtIndexPath没有返回更正属性有关。

感谢任何想法。

1 个答案:

答案 0 :(得分:0)

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

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

然后你需要在调用insertItemsAtIndexPaths

之前调用invalidateLayout方法

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