iOS 8 UICollectionViewLayout在Swift中切换神秘崩溃

时间:2015-05-13 23:47:58

标签: ios swift uicollectionview uicollectionviewlayout

我正在与UICollectionView合作。我正在尝试使用以下代码将UICollectionViewLayout从网格切换到列表,反之亦然:

@IBAction func switchLayout(sender: AnyObject) {
    isGridLayout = !isGridLayout

    collectionView?.reloadData()

    if isGridLayout {            

        collectionView?.performBatchUpdates({ () -> Void in
            self.collectionView?.collectionViewLayout.invalidateLayout()
            self.collectionView?.setCollectionViewLayout(self.gridLayout, animated: true)
            }, completion: { (completion) -> Void in
        })

    } else {            

        collectionView?.performBatchUpdates({ () -> Void in
            self.collectionView?.collectionViewLayout.invalidateLayout()
            self.collectionView?.setCollectionViewLayout(self.listLayout, animated: true)
            }, completion: { (completion) -> Void in
        })            
    }
}

我始终在setCollectionViewLayout:animated:方法上遇到以下崩溃,我不明白。任何有关修复此崩溃的帮助都会很棒!

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil (key: <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})'

该项目可在github中找到。它是tutorial的修改形式。

2 个答案:

答案 0 :(得分:1)

因为您在FlowLayout中设置了headerReferenceSize。这意味着collectionView将具有补充视图。

请注释headerReferenceSize的代码或在ViewController中实现collectionView(_:viewForSupplementaryElementOfKind:at:)

答案 1 :(得分:0)

我有类似的问题,最后我失踪了在UICollectionViewLayoutAttributes子类中实现layoutAttributesForItemAtIndexPath()。

这是我的实施

override func prepareLayout() {
    super.prepareLayout()

    if let numberOfItems = self.collectionView?.numberOfItemsInSection(0) {
        var left: CGFloat = self.sectionInset.left
        let centerY = CGRectGetMidY((self.collectionView?.bounds)!)
        for item in 0..<numberOfItems {
            let itemFrame = CGRect(origin: CGPoint(x: left, y: centerY - (self.itemSize.height / 2)), size: self.itemSize)
            let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: NSIndexPath(forItem: item, inSection: 0))
            attributes.size = ITEM_SIZE
            attributes.frame = itemFrame
            attributes.alpha = 1
            attributes.zIndex = 1
            attributes.hidden = false

            self.layoutAttributes.append(attributes)

            left += self.itemSize.width + self.minimumInteritemSpacing
        }

        let contentWidth: CGFloat = self.sectionInset.left + (CGFloat(numberOfItems) * (self.itemSize.width + self.minimumInteritemSpacing) - self.minimumInteritemSpacing) + self.sectionInset.right
        self.contentSize = CGSize(width: contentWidth, height: (self.collectionView?.bounds.height)!)
    }
}

override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
    return self.layoutAttributes[indexPath.item]
}

override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    var validAttributes = [UICollectionViewLayoutAttributes]()
    for attributes in self.layoutAttributes {
        if CGRectIntersectsRect(attributes.frame, rect) {
            validAttributes.append(attributes)
        }
    }

    return validAttributes
}

override func collectionViewContentSize() -> CGSize {
    return self.contentSize
}