Reputation: 229
I've written a custom layout for a collection view. Part of the collection view involves inserting new items at the top with an animation beginning from offscreen. In order to do this I'm using the usual initialLayouts method. I'm able to animate the object in correctly but there seems to be a strange problem that I can't work out.
The cell that I'm animating in appears immediately in it's final position and then a second cell animates into place from the expected offscreen position, disappearing once the animation is complete. All of my other animations for deletion, bounds change etc are fine, so I don't believe my layout caches are wrong and normal layout is perfect. Potentially this is a cell reuse issue?
I've created a quick video demoing the problem (inserts start from 7 seconds) http://cl.ly/WMei
Has anyone seen this behaviour before and could point me in the right direction?
Unfortunately I can't share the whole layout class however here are my layoutAttributes methods and the initial insert attributes, I can try and give more info where asked for. I appreciate this is a hard one to debug so thanks a lot for taking the time to check it out :).
Here are the attributes I apply for top inserts:
MCLTXGridLayoutAttributes *att = [(MCLTXGridLayoutAttributes*)[self.dataStructure itemAtIndexPath:itemIndexPath] copy];
att.alpha = 1.0;
CGRect newFrame = att.frame;
newFrame.origin.y = self.collectionView.bounds.origin.y - att.totalHeight;
att.frame = newFrame;
return att;
and the layout attributes method:
- (UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
MCLTXGridLayoutAttributes *att = [MCLTXGridLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGFloat randomTopPadding = (arc4random() % kMaxVerticalSpacing);
randomTopPadding += kMinVerticalSpacing;
NSInteger randomExtraPadding = (NSInteger)arc4random() % kOneInXChanceOfRecievingExtraPadding;
att.topPadding = randomTopPadding + (randomExtraPadding == 1 ? kItemRandomExtraPadding : 0);
NSUInteger column = [self.dataStructure indexForShortestColumn];
att.columnIndex = column;
CGFloat y = MAX(self.tmpCachedHeight, [self.dataStructure heightForColumnWithIndex:column] + kMinItemSpacing) + att.topPadding;
CGFloat height = [self.datasource collectionView:self.collectionView heightForItemAtIndex:indexPath];
CGRect frame = CGRectMake([self xOriginForColumn:column], y, self.cachedColumnWidth, height);
att.frame = frame;
att.layerPriority = [self.datasource collectionView:self.collectionView layerPriorityForItemAtIndexPath:indexPath];
att.zIndex = att.layerPriority * -10;
att.transform3D = CATransform3DIdentity;
att.transform = CGAffineTransformIdentity;
return att;
}
Upvotes: 1
Views: 953
Reputation: 229
I did eventually figure this out. We were using Magical Record and the problem came with the saving.
With my testing I was creating fake objects and saving using a background thread as you should do with MR. The problem was in our networking code that completely by accident was calling a write + save on the main thread context. This was a very small write but it was enough to upset the rendering and cause the visual ghosting effect.
If you're seeing this issue and you're using something like Magical Record or multithreaded core data along with fetched results controllers, then double check your save calls to make sure you aren't accidentally hitting the main thread.
Upvotes: 0