UICollectionView exception in UICollectionViewLayoutAttributes from iOS7

I have done a View in CollectionView with CustomLayout. In iOS6 it worked great but iOS7 it throws an exception like this.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:

'layout attributes for supplementary item at index path ( {length = 2, path = 0 - 0}) changed from CustomSupplementaryAttributes: 0xd1123a0 index path: (NSIndexPath: 0xd112580 {length = 2, path = 0 - 0}); element kind: (identifier); frame = (0 0; 1135.66 45); zIndex = -1; to CustomSupplementaryAttributes: 0xd583c80 index path: (NSIndexPath: 0xd583c70 {length = 2, path = 0 - 0}); element kind: (identifier); frame = (0 0; 1135.66 45); zIndex = -1; without invalidating the layout'

You need to invalidate the existing layout before updating, see the end of the error message:

without invalidating the layout'

[collectionViewLayout invalidateLayout];

Apple Documentation for UICollectionViewLayout

uicollectionviewlayout UICollectionView exception in , I have done a View in CollectionView with CustomLayout. In iOS6 it worked great but iOS7 it throws an exception like this. Terminating app due to uncaught  It's working perfectly on iOS6, but crashes in iOS7 with this exception: Assertion Failure in UICollectionViewData validateLayoutInRect. I delete the object from collectionArray then self.collectionView, one by one, using indexPath. When I delete the 4th object its raises Assertion failure on iOS7. Here I am using performBatchUpdates.

iOS 10

At iOS 10, a new feature is introduced, it is Cell Prefetching. It will let dynamic position of SupplementaryView crash. In order to run in the old behavior, it needs to disable prefetchingEnabled. It's true by default at iOS 10.

// Obj-C
// This function is available in iOS 10. Disable it for dynamic position of `SupplementaryView `.
if ([self.collectionView respondsToSelector:@selector(setPrefetchingEnabled:)]) {
    self.collectionView.prefetchingEnabled = false;
}

// Swift
if #available(iOS 10, *) { 
    // Thanks @maksa
    collectionView.prefetchingEnabled = false 

    // Swift 3 style
    colView.isPrefetchingEnabled = false   
}

I hate this problem. I spend 2 days for this problem. A reference about Cell Pre-fetch @iOS 10.


iOS 9 and before ...

@Away Lin is right.. I solve the same problem by implementing that delegate method.

My Custom UICollectionViewLayout will modify the attributes in layoutAttributesForElementsInRect. The section position is dynamic, not static. So, I obtain warnings about the layout attributes for supplementary item at index path ... changed from ... to .... Before the changes, invalideLayout related methods should be called.

And, after implementing this delegate method to return true, the method invalidateLayoutWithContext: will be called when scrolling the UICollectionViewLayout. By default, it returns false.

- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
    return YES;
}

From Apple Docs

Return Value true if the collection view requires a layout update or false if the layout does not need to change.

Discussion The default implementation of this method returns false. Subclasses can override it and return an appropriate value based on whether changes in the bounds of the collection view require changes to the layout of cells and supplementary views.

If the bounds of the collection view change and this method returns true, the collection view invalidates the layout by calling the invalidateLayoutWithContext: method.

Availability Available in iOS 6.0 and later.


And more ...

A nice example project on GitHub, for custom UICollectionViewLayout.

UICollectionViewLayoutAttributes, UICollectionView exception in UICollectionViewLayoutAttributes from iOS7. the view I have done a View in CollectionView with CustomLayout. In iOS6 it  He hecho una Vista en CollectionView con CustomLayout. En iOS6 funcionó muy bien, pero iOS7 se lanza una excepción como esta. De terminación de la

I had the same exception: in iOS 7, you need now to override the inherited isEqual: in your UICollectionViewLayoutAttributes subclass as stated in Apple documentation here.

UICollectionView or dancing with wolves / Sudo Null IT News, uicollectionviewlayout UICollectionView exception in UICollectionViewLayoutAttributes from iOS7? [collectionViewLayout invalidateLayout];. But when should  It seems that UIKit would crash when -scrollToItemAtIndexPath:atScrollPosition:Animated is called when the UICollectionView is not yet laid out, as you could see on Radar. So you can only put it in viewDidAppear and and viewDidLayoutSubviews on iOS7 and only put it in viewDidAppear on iOS6. why even viewDidLayoutSubviews is excluded on iOS6 is shown in your log:

I solved my problem by override the method at the subclase of UICollectionViewFlowLayout:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound

return YES

UICollectionView + UIKit Dynamics · objc.io, In iOS 7 and later, the collection view does not apply layout attributes if those attributes have not changed. It determines whether the attributes have changed by  Uncaught exception: layout attributes for supplementary item at index path (<NSIndexPath: 0xc000000000000116> {length = 2, path = 1 - 0}) changed from <UICollectionViewLayoutAttributes: 0x6080001ec400> index path:

I'm not entirely certain how or why, but this appears to be fixed in iOS 12, supporting both supplementary view resizing and prefetching. The trick for me was to make sure things are happening in the correct order.

Here is a working implementation of a stretchable header view. Notice the implementation of the header resizing happening in layoutAttributesForElements(in rect: CGRect):

class StretchyHeaderLayout: UICollectionViewFlowLayout {

    var cache = [UICollectionViewLayoutAttributes]()

    override func prepare() {
        super.prepare()

        cache.removeAll()

        guard let collectionView = collectionView else { return }

        let sections = [Int](0..<collectionView.numberOfSections)
        for section in sections {
            let items = [Int](0..<collectionView.numberOfItems(inSection: section))
            for item in items {
                let indexPath = IndexPath(item: item, section: section)
                if let attribute = layoutAttributesForItem(at: indexPath) {
                    cache.append(attribute)
                }
            }
        }

        if let header = layoutAttributesForSupplementaryView(ofKind: StretchyCollectionHeaderKind, at: IndexPath(item: 0, section: 0)) {
            cache.append(header)
        }
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true
    }

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

        let visibleAttributes = cache.filter { rect.contains($0.frame) || rect.intersects($0.frame) }

        guard let collectionView = collectionView else { return visibleAttributes }

        // Find the header and stretch it while scrolling.
        guard let header = visibleAttributes.filter({ $0.representedElementKind == StretchyCollectionHeaderKind }).first else { return visibleAttributes }
        header.frame.origin.y = collectionView.contentOffset.y
        header.frame.size.height = headerHeight.home - collectionView.contentOffset.y
        header.frame.size.width = collectionView.frame.size.width

        return visibleAttributes
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attributes = super.layoutAttributesForItem(at: indexPath as IndexPath)?.copy() as! UICollectionViewLayoutAttributes
        guard collectionView != nil else { return attributes }

        attributes.frame.origin.y =  headerHeight.home + attributes.frame.origin.y

        return attributes
    }

    override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        return UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: StretchyCollectionHeaderKind, with: indexPath)
    }

    override var collectionViewContentSize: CGSize {
        get {
            guard let collectionView = collectionView else { return .zero }

            let numberOfSections = collectionView.numberOfSections
            let lastSection = numberOfSections - 1
            let numberOfItems = collectionView.numberOfItems(inSection: lastSection)
            let lastItem = numberOfItems - 1

            guard let lastCell = layoutAttributesForItem(at: IndexPath(item: lastItem, section: lastSection)) else { return .zero }

            return CGSize(width: collectionView.frame.width, height: lastCell.frame.maxY + sectionInset.bottom)
        }
    }
}

P.S.: I'm aware the cache doesn't actually serve any purpose at this point :)

UICollectionView or dancing with wolves, The dream UICollectionView is the UIKit class introduced in iOS 6. Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '​request for index iOS 7. 1. If the cell is the last in the section, as well as the presence of footers in the reason: 'no UICollectionViewLayoutAttributes instance for  The accepted answer (by titaniumdecoy) is correct.I just wanted to share my own experience with this issue as well as the solution I came up with. I was using a custom decorator to create a divider (separators) between cells and after a while I decided to add headers to sections as well and this caused the internal inconsistency crash.

UICollectionViewTransitionLayout Class (UIKit), UIKit Dynamics is the new physics-based animation engine in iOS 7 – it has been for each UICollectionViewLayoutAttributes object in the collection view (later, animator, then we can't re-add it or we'll get a very obscure runtime exception: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21: NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewLayoutAttributes : NSObject <NSCopying, UIDynamicItem>

The dream UICollectionView is a UIKit class that appeared in iOS 6. Strictly Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 1 iOS 7. 1. In case the cell is the last in the section, as well as the presence of footers in the reason: 'no UICollectionViewLayoutAttributes instance for  A Tour of UICollectionView Debugging Update Exceptions 225_A Tour of Collection View - 2018 WWDC_03_D Created Date:

A UICollectionViewLayout that is used temporarily when a UICollectionView is transitioning iOS, 7, 0, ObjCRuntime. GetInvalidationContext(​UICollectionViewLayoutAttributes If not overridden, raises an NSUndefinedKeyException. UIKit Dynamics is the new physics-based animation engine in iOS 7 – it has been specifically designed to work well with collection views, which were first introduced in iOS 6. We’re going to take a tour of how you put these two together. This article is going to discuss two examples of using collection views with UIKit Dynamics.

Comments
  • Yes I have override that method. But still getting the same. Finally I have fixed the issue. What I have done is whenever changing the collectionview frame I'm doing invalidateLayout for that collectionview.
  • Could you upvote this question or mark it as correct if it has helped? As invalidating the layout was the solution and you didn't post any code
  • Showing code for how to invalidate the layout would be actually useful instead of just linking to the documentation
  • But when should you invalidate the layout? "before updating" what? In my case this exception happens when rotating to landscape.
  • This answer should clarify "before updating." (Before updating the contents in the CollectionView? Before the view updates its layout attributes with preferred ones?)
  • I'd give you all the upvotes out there for the iOS10 thing, it's been bugging me for a week. To try to add some value here's the Swift solution: if #available(iOS 10, *) { collectionView.prefetchingEnabled = false }
  • thank you so much for the ios 10 update.. I was trying since morning and found your answer which helped me to resolve problem in a minute. I have upvoted.
  • This is the correct answer to the question. invalidating items (cells) would throw exception unless you'd disable pre-fetching.
  • this should be the correct answer. This fixed the problem for me!
  • please add some more details to answer!
  • not sure why this answer is downvoted. this is exactly what worked for me! thanks!