Expose UICollectionViewLayoutInvalidationContext.updateItems
| Originator: | zach | ||
| Number: | rdar://27161788 | Date Originated: | 04-Jul-2016 12:22 PM |
| Status: | Open | Resolved: | false |
| Product: | iOS SDK | Product Version: | iOS 10.0 (14A5261v) |
| Classification: | Enhancement | Reproducible: | Sometimes |
Summary: My reading of the intended use of UICollectionViewLayout's invalidation workflow (as it exists starting in iOS 7) is to use `invalidateDataSourceCounts` as a indication to throw away or set-needs-update the data for the layout. Normally, my layout would do a naïve diff based on the counts of the old data structure and new data source to add and remove elements from my layout's data structures, but I emphasize this is a naïve pass. Rebuilding the layout isn't suitable when implemented using self-sizing elements in iOS 8. An update animation would then cause all elements to animatedly shrink to their estimate, before cutting to their self-sizing height at the end of the animation as another layout pass is applied. The only way to get properly incremental information is `UICollectionViewLayout.prepareForCollectionViewUpdates(_:)`, but that's only called after a full invalidation and rect-query, counter to its documentation. Steps to Reproduce: 1. Implement `UICollectionViewLayout.prepareForCollectionViewUpdates(_:)`. 2. Set up a deleteItemsAtIndexPaths(_:) or deleteSections(_:) batch update. 3. Notice incorrect information is recorded. 4. Add logging throughout your layout. 5. Notice a full pass of `invalidateLayoutWithContext(_:)` and `layoutAttributesForElementsInRect(_:)` is triggered before getting to `prepareForCollectionViewUpdates(_:)` Expected Results: My layout is able to record information about deleted elements in its layout data prior to having its information thrown away by `invalidateLayoutWithContext(_:)`. Actual Results: In debugging, notice that the invalidation that happens during directly during the processing of batch updates has an `_updateItems` ivar in LLDB. Become very sad. Version: iOS 10.0 (14A5261v) Notes: I was able to create a workable solution by having UICollectionViewLayoutInvalidationContext.invalidateDataSourceCounts set a "ignore" flag in my layout, which ignores all requests to `layoutAttributesForElementsInRect(_:)` et. al. until `prepareForCollectionViewUpdates(_:)` is reached, at which point I do a more appropriate incremental layout invalidation. This solution is suboptimal; the `prepareFor` workflows in `UICollectionViewLayout` are outdated. Invalidation contexts should be the only mechanism by which changes occur to the layout for maximum performance. It seems you folks already realize this, because updates already go through that. It would seem UICollectionViewFlowLayout is spared from this pain by using the default update-prep logic defined in the superclass. That logic isn't suitable for every kind of layout. :-/ Configuration: iPhone 6s Plus 64GB T-Mobile, using Wi-Fi Attachments:
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!