I'm using a custom UICollectionViewLayout like this :
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
}
That's works as I want but if I wanna insert an other item, my app crash with this error :
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
This is the code I use to insert the new item
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)
}
Any idea ?
Base on the error message, this is because of the cell can't retrieve layoutAttributes.
layoutAttributesForItemAtIndexPath
returns nil if cell which will be created by update is not visible.
To fix this error, override layoutAttributesForItemAtIndexPath
method:
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
return cache[indexPath.row]
}
SWIFT 3 -
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cache[indexPath.row]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With