我有一个 UICollectionView,其内容由 NSFetchedResultsController 提供。每当更新核心数据时,都会通过 reloadItemsAtIndexPaths: 方法调用以更新集合视图中更改的项目。
经过大量测试,我确定上述过程正常工作。我对核心数据进行了更新,最终调用了数据源方法“cellForItemAtIndexPath”并按预期更新了单元格。但是,我还实现了数据源方法“viewForSupplementaryElementOfKind”,以显示一些单元格标题(也基于对核心数据的更改),但这无法正常工作。
出于某种原因,似乎在核心数据更改后调用“reloadItemsAtIndexPaths”时,不会调用“viewForSupplementaryElementOfKind”,我无法弄清楚为什么会出现这种情况。但是,一旦我开始滚动集合视图,就会调用“viewForSupplementaryElementOfKind”,并且我可以根据核心数据更改在补充标题视图中看到更新。在初始创建 UICollectionView 时也会成功调用此方法。
我有一个与我的集合视图一起使用的自定义布局,所以问题可能出在那儿?我希望有人能发现我的错误。
下面是创建 UICollectionView、它的布局、单元格和它的标题视图的代码:
创建 UICollectionView
- (void)createCollectionView { _layout1 = [[BigLayout alloc] init]; //custom layout [_layout1 setScrollDirection:UICollectionViewScrollDirectionHorizontal]; _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout1]; _collectionView.translatesAutoresizingMaskIntoConstraints = NO; _collectionView.backgroundColor = [UIColor clearColor]; _collectionView.dataSource = self; _collectionView.delegate = self; [self.view addSubview:_collectionView]; //set up constraints, add them to view... [self.collectionView registerClass:[InboxCell class] forCellWithReuseIdentifier:@"inbox"]; [self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"]; }
创建自定义布局
@implementation BigLayout -(id)init { self = [super init]; if (self) { self.itemSize = CGSizeMake(330, 588); self.scrollDirection = UICollectionViewScrollDirectionHorizontal; self.headerReferenceSize = CGSizeMake(13, 13); } return self; } -(void)prepareLayout { [super prepareLayout]; _cellCount = [[self collectionView] numberOfItemsInSection:0]; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path { UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path]; attributes.size = self.itemSize; attributes.center = CGPointMake(path.item * (self.itemSize.width + 20) + self.itemSize.width/2.0 + 20, self.collectionView.center.y); return attributes; } - (CGSize)collectionViewContentSize { return CGSizeMake(((self.itemSize.width + 20) * _cellCount) + 80, [self collectionView].height); } -(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { NSMutableArray* attributes = [NSMutableArray array]; for (NSInteger i=0 ; i < self.cellCount; i++) { NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0]; UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:indexPath]; UICollectionViewLayoutAttributes *hattr = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; if (CGRectIntersectsRect(attr.frame, rect)) { [attributes addObject:attr]; [attributes addObject:hattr]; } } return attributes; } - (void)prepareForCollectionViewUpdates:(NSArray *)updateItems { } - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath { UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; attributes.alpha = 1.0; return attributes; } - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath]; attributes.size = CGSizeMake(13, 13); attributes.center = CGPointMake(indexPath.item * (self.itemSize.width + 20) + self.itemSize.width/2.0 + 20 + self.collectionView.left, self.collectionView.height == 768 ? 75 : 200); attributes.alpha = 1.0f; return attributes; }
单元格的数据源方法(在 CD 更新中调用)
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { //this method gets called on reload items InboxCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"inbox" forIndexPath:indexPath]; Email *email = [self.fetchedResultsController objectAtIndexPath:indexPath]; //do stuff with the email in the cell return cell; }
补充标题视图的数据源方法(在 CD 更新中不调用)
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { //this method does not get called on reload items, only gets called initially and on scroll UICollectionReusableView *reusableView; if (kind == UICollectionElementKindSectionHeader) { //specify in case we add a footer later UICollectionReusableView *unreadEmailImageIdentifier = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath]; Email *email = [self.fetchedResultsController objectAtIndexPath:indexPath]; UIImageView *unreadEmailDot = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"dot.png"]]; [unreadEmailImageIdentifier addSubview:unreadEmailDot]; unreadEmailImageIdentifier.hidden = YES; if (email.isUnread == YES || email.isUnread == 1) { unreadEmailImageIdentifier.hidden = NO; } reusableView = unreadEmailImageIdentifier; } return reusableView; }
简而言之,当我尝试重新加载集合视图或集合视图的组件时,似乎没有调用补充标题视图的数据源方法。但是,我确实看到在自定义布局类中为补充视图创建属性的方法被调用了。如果有人能指出发生这种情况的任何可能原因,我将不胜感激!