Avoid animation of UICollectionView after reloadItemsAtIndexPaths
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When you call reloadItems(at:) on a UICollectionView, UIKit performs a fade animation by default. This is often unwanted — if you are updating cell content (like a counter or image), the fade looks jarring. The fix is to wrap the reload in UIView.performWithoutAnimation or use performBatchUpdates with animations disabled. Each approach disables the implicit animation that UIKit applies to collection view updates.
The Problem
UIKit wraps reloadItems(at:) in a CATransaction with a default fade animation. Even though you did not request an animation, the cells briefly fade out and back in.
Fix 1: UIView.performWithoutAnimation (Recommended)
This wraps the reload in a CATransaction that disables all animations for its duration. The cells update instantly with no visual transition.
For multiple index paths:
Fix 2: performBatchUpdates with Animations Disabled
This globally disables animations during the batch update. Re-enable animations in the completion block to avoid affecting other UI elements.
Fix 3: CATransaction
setDisableActions(true) suppresses all implicit Core Animation actions (including the fade) within the transaction.
Fix 4: Reconfigure Cells (iOS 15+)
Starting with iOS 15, reconfigureItems(at:) updates cell content without replacing the cell, which means no animation:
This calls your cell configuration closure again for the specified items without creating new cells or triggering any animation. It is the cleanest solution if you target iOS 15 or later.
Fix 5: Update Cell Directly
Skip reloadItems entirely and update the cell in place:
This modifies the existing cell without involving the collection view's update mechanism. No animation occurs because no reload happens.
Reloading Entire Sections Without Animation
The same approach works for reloadSections(_:) and reloadData():
Note that reloadData() does not normally animate, but can inherit animations from a surrounding animation block.
UITableView Equivalent
The same techniques work for UITableView:
For UITableView, you can also pass .none as the animation parameter:
UICollectionView does not have this animation parameter — which is why the wrapper approaches are necessary.
Common Pitfalls
- Forgetting to re-enable animations: When using
UIView.setAnimationsEnabled(false), always re-enable in the completion block. Leaving animations disabled globally breaks all subsequent UI animations. - Using
reloadData()when you meanreloadItems(at:):reloadData()replaces all cells and resets scroll position. UsereloadItems(at:)for targeted updates. - Calling
cellForItem(at:)on off-screen cells: If the cell is not visible,cellForItem(at:)returnsnil. Only use the direct-update approach for visible cells. - Mixing animated and non-animated updates: If you perform animated inserts/deletes in the same batch as non-animated reloads, the animation disabling affects everything. Separate them into different batch updates.
- iOS version compatibility:
reconfigureItems(at:)requires iOS 15+. Check availability before using it:if #available(iOS 15.0, *) { ... }.
Summary
reloadItems(at:)triggers a default fade animation on UICollectionView- Wrap in
UIView.performWithoutAnimation { }to suppress the animation - Use
CATransaction.setDisableActions(true)as an alternative - On iOS 15+, use
reconfigureItems(at:)which never animates - Update cells directly via
cellForItem(at:)to bypass the reload mechanism entirely - UITableView has a
.noneanimation parameter but UICollectionView does not

