Crashing While Collection View Cell Deletion Because of "Uicollectionviewlayoutattributes"

Using [UICollectionView performBatchUpdates:] with a UICollectionViewFlowLayout that has UIDynamics

try

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes = [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath];
if(!layoutAttributes) {
layoutAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
}
return layoutAttributes;
}

when you execute performBatchUpdates, [self.dynamicAnimator layoutAttributesForCellAtIndexPath: returns nil if cell which will be created by update is not visible.
So just returns super(perhaps UICollectionViewFlowLayout)'
s layoutAttributes for now.
And when the cell about to be displayed, UIDynamicAnimator will do the job for you.

UICollectionViews GetSizeForItem() crashes on call of collectionView.DequeueReusableCell ()

So for anyone who stumbles across the same Problem.

Frankly speaking there is just a different behaviour between UITableView and UICollectionView.
Where in UITableView it is totally ok to call dequeueReusableCellWithReuseIdentifier() in getHeightForRow() to get a cell for height calculation, calling it in sizeForItemAtIndexPath in a UICollectionView will cause an indefinite loop and thus crash the app.

Thx to @Markus Rautopuro for point me in the right direction with his Answer

I'm now calculating the height of the cell, by calculating the size of the components in the cell. That works quite well and needs less resources, since i don't need to build a complete cell, but only the items, that add up to the height.

UICollectionView exception in UICollectionViewLayoutAttributes from iOS7

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

Scroll to item in collection view crashes the app

I had the same problem and could solve it. First of all, when you create the UICollectionView you must specify a frame with its width, no matters the height, but the width it's very important to scroll to the correct item.

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
[layout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
collectionView_ = [[UICollectionView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, CGRectGetWidth([scrollView_ frame]), 0.0f)
collectionViewLayout:layout];
[collectionView_ setDelegate:self];
[collectionView_ setDataSource:self];
[collectionView_ setBackgroundColor:[UIColor clearColor]];
[collectionView_ setTranslatesAutoresizingMaskIntoConstraints:NO];
[collectionView_ setShowsHorizontalScrollIndicator:NO];
[collectionView_ setPagingEnabled:YES];
[scrollView_ addSubview:collectionView_];

After creating the UICollectionView you must tell the view that needs update its constraints, because in iOS6 you have to force it, so invoke updateViewConstraints:

[self updateViewConstraints]

Override the method updateViewConstraints, and set here all the view constraints. Remember to remove all the constraints of the view before invoke super (in your code you are not removing them), and set on metrics' dictionary the width of the UICollectionView and don't use [collectionView_(==scrollView_)] because sometimes it fails, mainly in iOS6.

- (void)updateViewConstraints {

[scrollView_ removeConstraints:[scrollView_ constraints]];
[super updateViewConstraints];

NSDictionary *views = [self viewsDictionary];
NSDictionary *metrics = @{ @"bigMargin" : @12, @"collectionViewHeight" : @(collectionViewHeight_), @"viewWidth" : @(CGRectGetWidth([scrollView_ frame]) };

NSMutableString *verticalConstraints = [NSMutableString stringWithString:@"V:|[collectionView_(==collectionViewHeight)]"];

[scrollView_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[collectionView_(==viewWidth)]|"
options:0
metrics:nil
views:views]];

if (extendedInformationView_) {

[scrollView_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[extendedInformationView_(==scrollView_)]|"
options:0
metrics:nil
views:views]];

[verticalConstraints appendFormat:@"-bigMargin-[extendedInformationView_]"];
}

if (actionListView_) {

[scrollView_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[actionListView_(==scrollView_)]|"
options:0
metrics:nil
views:views]];

[verticalConstraints appendFormat:@"-bigMargin-[actionListView_]"];
}

[verticalConstraints appendString:@"-bigMargin-|"];

[scrollView_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:verticalConstraints
options:0
metrics:metrics
views:views]];

}

Finally, to scroll the UICollectionView to the correct item, do it on viewWillLayoutSubviews and don't forget to check if UICollectionView's size is not zero to avoid app crash:

- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];

if (!CGSizeEqualToSize([collectionView_ frame].size, CGSizeZero)) {

[collectionView_ scrollToItemAtIndexPath:_selectedRowItem_ inSection:0]
atScrollPosition:UICollectionViewScrollPositionLeft
animated:NO];
}
}

That's all. Hope it helps!

NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath, custom layout

For those who encounter the same issue, I discovered that when you do

self.collectionView?.performBatchUpdates({ () -> Void in
// add new items into collection
self.collectionView?.insertItemsAtIndexPaths(indexPaths)

}, completion: { (finished) -> Void in
// do insertion animations
});

the layoutAttributesForElementsInRect method is not called and the layoutAttributesForItemAtIndexPathis called instead.

Therefore, you must also override layoutAttributesForItemAtIndexPath in the custom layout like so:

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

// Logic that calculates the UICollectionViewLayoutAttributes of the item
// and returns the UICollectionViewLayoutAttributes
return self.singleItemLayout(indexPath)
}

EDIT: Also, if you encounter flicker when the batch insertItemsAtIndexPaths method on it's own.

UICollection View Reload Data After Scrolling Crash

I have managed to get around the issue by using the UICollectionView.reloadSections(sections: IndexSet) method. This doesn't cause any crashes. I loop through all sections and add each section to an IndexSet variable then use that in the reload sections method like this;

 var indexSet = IndexSet()

let rowCount = collectionView.numberOfSections

for row in 0..<rowCount {

indexSet = [row]

collectionView.reloadSections(indexSet)
}


Related Topics



Leave a reply



Submit