我刚刚遇到了类似的问题,但是找到了一个完全不同的解决方案。
我正在使用UICollectionViewFlowLayout的自定义实现和水平滚动。我还在为每个单元格创建自定义框架位置。
我遇到的问题是,[super layoutAttributesForElementsInRect:rect]并未真正返回应该在屏幕上显示的所有UICollectionViewLayoutAttributes。在调用[self.collectionView reloadData]时,某些单元格会突然设置为隐藏。
我最终要做的是创建一个NSMutableDictionary,它缓存了到目前为止我已经看到的所有UICollectionViewLayoutAttributes,然后包括了我应该显示的所有项目。
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray * originAttrs = [super layoutAttributesForElementsInRect:rect];
NSMutableArray * attrs = [NSMutableArray array];
CGSize calculatedSize = [self calculatedItemSize];
[originAttrs enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * attr, NSUInteger idx, BOOL *stop) {
NSIndexPath * idxPath = attr.indexPath;
CGRect itemFrame = [self frameForItemAtIndexPath:idxPath];
if (CGRectIntersectsRect(itemFrame, rect))
{
attr = [self layoutAttributesForItemAtIndexPath:idxPath];
[self.savedAttributesDict addAttribute:attr];
}
}];
[self.savedAttributesDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSArray * cachedAttributes, BOOL *stop) {
CGFloat columnX = [key floatValue];
CGFloat leftExtreme = columnX;
CGFloat rightExtreme = columnX + calculatedSize.width;
if (leftExtreme <= (rect.origin.x + rect.size.width) || rightExtreme >= rect.origin.x) {
for (UICollectionViewLayoutAttributes * attr in cachedAttributes) {
[attrs addObject:attr];
}
}
}];
return attrs;
}
这是NSMutableDictionary的类别,UICollectionViewLayoutAttributes已正确保存。
#import "NSMutableDictionary+CDBCollectionViewAttributesCache.h"
@implementation NSMutableDictionary (CDBCollectionViewAttributesCache)
- (void)addAttribute:(UICollectionViewLayoutAttributes*)attribute {
NSString *key = [self keyForAttribute:attribute];
if (key) {
if (![self objectForKey:key]) {
NSMutableArray *array = [NSMutableArray new];
[array addObject:attribute];
[self setObject:array forKey:key];
} else {
__block BOOL alreadyExists = NO;
NSMutableArray *array = [self objectForKey:key];
[array enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *existingAttr, NSUInteger idx, BOOL *stop) {
if ([existingAttr.indexPath compare:attribute.indexPath] == NSOrderedSame) {
alreadyExists = YES;
*stop = YES;
}
}];
if (!alreadyExists) {
[array addObject:attribute];
}
}
} else {
DDLogError(@"%@", [CDKError errorWithMessage:[NSString stringWithFormat:@"Invalid UICollectionVeiwLayoutAttributes passed to category extension"] code:CDKErrorInvalidParams]);
}
}
- (NSArray*)attributesForColumn:(NSUInteger)column {
return [self objectForKey:[NSString stringWithFormat:@"%ld", column]];
}
- (void)removeAttributesForColumn:(NSUInteger)column {
[self removeObjectForKey:[NSString stringWithFormat:@"%ld", column]];
}
- (NSString*)keyForAttribute:(UICollectionViewLayoutAttributes*)attribute {
if (attribute) {
NSInteger column = (NSInteger)attribute.frame.origin.x;
return [NSString stringWithFormat:@"%ld", column];
}
return nil;
}
@end