使用自定义UICollectionViewLayout

时间:2015-05-31 20:45:03

标签: ios swift uicollectionview uicollectionviewlayout

我正在使用这样的自定义UICollectionViewLayout:

override func prepareLayout() {
        cache.removeAll(keepCapacity: false)

        let standardHeight = LayoutConstants.Cell.standardHeight
        let featuredHeight = LayoutConstants.Cell.featuredHeight

        var frame = CGRectZero
        var y: CGFloat = 0

        for item in 0..<numberOfItems {
            let indexPath = NSIndexPath(forItem: item, inSection: 0)
            let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
            let cell = collectionView!.cellForItemAtIndexPath(indexPath)
            /* Important because each cell has to slide over the top of the previous one */
            attributes.zIndex = item
            /* Initially set the height of the cell to the standard height */
            var height = standardHeight
            if indexPath.item == featuredItemIndex {
                /* The featured cell */
                let yOffset = standardHeight * nextItemPercentageOffset
                y = collectionView!.contentOffset.y - yOffset
                height = featuredHeight
            } else if indexPath.item == (featuredItemIndex + 1) && indexPath.item != numberOfItems {
                /* The cell directly below the featured cell, which grows as the user scrolls */
                let maxY = y + standardHeight
                height = standardHeight + max((featuredHeight - standardHeight) * nextItemPercentageOffset, 0)
                y = maxY - height
            }
            frame = CGRect(x: 0, y: y, width: width, height: height)
            attributes.frame = frame
            cache.append(attributes)
            y = CGRectGetMaxY(frame)
        }
    }

    /* Return all attributes in the cache whose frame intersects with the rect passed to the method */
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
        var layoutAttributes = [UICollectionViewLayoutAttributes]()
        for attributes in cache {
            if CGRectIntersectsRect(attributes.frame, rect) {
                layoutAttributes.append(attributes)
            }
        }
        return layoutAttributes
    }

这是我想要的,但如果我想插入其他项目,我的应用程序崩溃了这个错误:

2015-05-31 22:37:29.032 Flore-Jessy[15359:717220] *** Assertion failure in -[UICollectionViewData layoutAttributesForItemAtIndexPath:], /SourceCache/UIKit_Sim/UIKit-3347.44/UICollectionViewData.m:694
2015-05-31 22:37:29.077 Flore-Jessy[15359:717220] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath: <NSIndexPath: 0x7b952a70> {length = 2, path = 0 - 15}'
*** First throw call stack:
(
    0   CoreFoundation                      0x00a0a746 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x02867a97 objc_exception_throw + 44
    2   CoreFoundation                      0x00a0a5da +[NSException raise:format:arguments:] + 138
    3   Foundation                          0x01093720 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 118
    4   UIKit                               0x01de5c74 -[UICollectionViewData layoutAttributesForItemAtIndexPath:] + 461
    5   UIKit                               0x01dafbe7 __51-[UICollectionView _viewAnimationsForCurrentUpdate]_block_invoke1382 + 161
    6   UIKit                               0x01dad73b -[UICollectionView _viewAnimationsForCurrentUpdate] + 4789
    7   UIKit                               0x01db0eb8 -[UICollectionView _updateWithItems:tentativelyForReordering:] + 2447
    8   UIKit                               0x01dabf0d -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:] + 14802
    9   UIKit                               0x01da8536 -[UICollectionView _endItemAnimationsWithInvalidationContext:] + 48
    10  UIKit                               0x01da82ed -[UICollectionView _updateRowsAtIndexPaths:updateAction:] + 374
    11  UIKit                               0x01da833f -[UICollectionView insertItemsAtIndexPaths:] + 48
    12  Flore-Jessy                         0x0009183c _TFC11Flore_Jessy22TimelineViewController13viewDidAppearfS0_FSbT_ + 556
    13  Flore-Jessy                         0x000918cf _TToFC11Flore_Jessy22TimelineViewController13viewDidAppearfS0_FSbT_ + 63
    14  UIKit                               0x017f3245 -[UIViewController _setViewAppearState:isAnimating:] + 629
    15  UIKit                               0x017f3860 -[UIViewController __viewDidAppear:] + 171
    16  UIKit                               0x017f3b2b -[UIViewController _endAppearanceTransition:] + 322
    17  UIKit                               0x0180bd4e -[UIViewController(UIContainerViewControllerProtectedMethods) endAppearanceTransition] + 41
    18  UIKit                               0x017c403b -[UIPresentationController transitionDidFinish:] + 839
    19  UIKit                               0x01e50109 -[_UIFullscreenPresentationController transitionDidFinish:] + 59
    20  UIKit                               0x017c6c11 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 165
    21  UIKit                               0x01ef444a -[_UIViewControllerTransitionContext completeTransition:] + 124
    22  Flore-Jessy                         0x0008e174 _TFFC11Flore_Jessy29SwipeBluredTransitionAnimator17animateTransitionFS0_FPSo36UIViewControllerContextTransitioning_T_U0_FSbT_ + 436
    23  Flore-Jessy                         0x0008ca34 _TPA__TFFC11Flore_Jessy29SwipeBluredTransitionAnimator17animateTransitionFS0_FPSo36UIViewControllerContextTransitioning_T_U0_FSbT_ + 68
    24  Flore-Jessy                         0x0008e1bc _TTRXFo_dSb_dT__XFo_iSb_iT__ + 28
    25  Flore-Jessy                         0x0008caea _TPA__TTRXFo_dSb_dT__XFo_iSb_iT__ + 90
    26  Flore-Jessy                         0x0008e1f7 _TTRXFo_iSb_iT__XFo_dSb_dT__ + 39
    27  Flore-Jessy                         0x0008cb9e _TPA__TTRXFo_iSb_iT__XFo_dSb_dT__ + 78
    28  Flore-Jessy                         0x0008e245 _TTRXFo_dSb_dT__XFdCb_dV10ObjectiveC8ObjCBool_dT__ + 69
    29  UIKit                               0x017149be -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 318
    30  UIKit                               0x016f81b2 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 206
    31  UIKit                               0x016f8522 -[UIViewAnimationState animationDidStop:finished:] + 80
    32  QuartzCore                          0x0154a571 _ZN2CA5Layer23run_animation_callbacksEPv + 307
    33  libdispatch.dylib                   0x02f59bef _dispatch_client_callout + 14
    34  libdispatch.dylib                   0x02f3f6bb _dispatch_main_queue_callback_4CF + 993
    35  CoreFoundation                      0x009638ee __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14
    36  CoreFoundation                      0x009215f0 __CFRunLoopRun + 2256
    37  CoreFoundation                      0x00920a5b CFRunLoopRunSpecific + 443
    38  CoreFoundation                      0x0092088b CFRunLoopRunInMode + 123
    39  GraphicsServices                    0x051e02c9 GSEventRunModal + 192
    40  GraphicsServices                    0x051e0106 GSEventRun + 104
    41  UIKit                               0x0168a106 UIApplicationMain + 1526
    42  Flore-Jessy                         0x00080a24 main + 180
    43  libdyld.dylib                       0x02f84ac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

这是我用来插入新项目的代码

override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        if let post = newPost {

collectionView!.insertItemsAtIndexPaths([dataSource.indexPathForNewPost(post)])
        }
    }

/// Return the new indexPath for the TimelineItem
    func indexPathForNewPost(item: TimelineItem) -> NSIndexPath {
        if let liste = listPosts {
            listPosts!.append(item)
        }
        return indexPathForPost(item)
    }

    func indexPathForPost(item: TimelineItem) -> NSIndexPath {
        var itemIndex = 0
        for (index, currentTimelineItem) in enumerate(allPosts()) {
            if currentTimelineItem === item {
                itemIndex = index
                break
            }
        }
        return NSIndexPath(forItem: itemIndex, inSection: 0)
    }

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

基于错误消息,这是因为单元格无法检索layoutAttributes。 如果将通过更新创建的单元格不可见,则layoutAttributesForItemAtIndexPath将返回nil。

要修复此错误,请覆盖layoutAttributesForItemAtIndexPath方法:

override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
        return cache[indexPath.row]
    }

SWIFT 3 -

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
    return cache[indexPath.row]
  }