UICollectionView decoration views duplicate in view after performBatchUpdates
| Originator: | duncan | ||
| Number: | rdar://12623956 | Date Originated: | 11/2/12 |
| Status: | Unresolved | Resolved: | |
| Product: | iPhone | Product Version: | iOS 6.0 |
| Classification: | Serious Bug | Reproducible: | Always |
02-Nov-2012 11:58 AM Duncan Lewis:
Summary:
Decoration views are duplicated in the UICollectionView view hierarchy when changes to the UICollectionViewLayout are animated using the UICollectionView method `performBatchUpdates:completion:`
Steps to Reproduce:
1. Create a UICollectionView subclass
@interface MyDecorationView : UICollectionReusableView
@end
@implementation MyDecorationView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.5f];
}
return self;
}
@end
@interface MyCollectionViewLayout : UICollectionViewFlowLayout
@property (nonatomic, assign) BOOL flag;
@end
@implementation MyCollectionViewLayout
- (id)init
{
self = [super init];
if(self) {
[self registerClass:[MyDecorationView class] forDecorationViewOfKind:kDecorationKind];
}
return self;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath
{
if ([decorationViewKind isEqualToString:kDecorationKind]) {
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath];
layoutAttributes.frame = CGRectMake(0.0, 0.0, self.collectionViewContentSize.width, self.collectionViewContentSize.height);
return layoutAttributes;
}
return nil;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *attributeArray = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
// add decoration
if (self.flag) {
[attributeArray addObject:[self layoutAttributesForDecorationViewOfKind:kDecorationKind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]];
}
return attributeArray;
}
@end
2. Create a UICollectionView with the above custom layout as its layout object. Place the collectionView in a view.
3. Add a method to toggle the "flag" property on the collectionView's custom layout and call performBatchUpdates like so:
- (void)toggle
{
MyCollectionViewLayout *layout = self.collectionView.collectionViewLayout;
[layout setFlag:!layout.flag];
[self.collectionView performBatchUpdates:nil completion:nil];
}
Expected Results:
When layout.flag == YES, decoration view should be visible after performBatchUpdates.
When layout.flag == NO, decoration view should not be visible after performBatchUpdates.
Actual Results:
Regardless of the value of layout.flag, and regardless of whether the decoration view layout attributes are added to the attributes array in `layoutAttributesForElementsInRect:`, the decoration view is duplicated in the collectionView view hierarchy.
Since the decoration view class has a background color of black and an alpha of 0.5, this can be observed by the continual darkening of the collectionView as successive performBatchUpdates calls are made.
Regression:
Notes:
Decoration views appear to be correctly removed from the collectionView when the method of update does not perform animations, e.g. calling invalidateLayout on the layout object instead of calling performBatchUpdates on the collectionView object after toggling the `flag` value causes the UI to be updated as expected.
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!