1

我有一个 UICollectionView,其内容由 NSFetchedResultsController 提供。每当更新核心数据时,都会通过 reloadItemsAtIndexPaths: 方法调用以更新集合视图中更改的项目。

经过大量测试,我确定上述过程正常工作。我对核心数据进行了更新,最终调用了数据源方法“cellForItemAtIndexPath”并按预期更新了单元格。但是,我还实现了数据源方法“viewForSupplementaryElementOfKind”,以显示一些单元格标题(也基于对核心数据的更改),但这无法正常工作。

出于某种原因,似乎在核心数据更改后调用“reloadItemsAtIndexPaths”时,不会调用“viewForSupplementaryElementOfKind”,我无法弄清楚为什么会出现这种情况。但是,一旦我开始滚动集合视图,就会调用“viewForSupplementaryElementOfKind”,并且我可以根据核心数据更改在补充标题视图中看到更新。在初始创建 UICollectionView 时也会成功调用此方法。

我有一个与我的集合视图一起使用的自定义布局,所以问题可能出在那儿?我希望有人能发现我的错误。

下面是创建 UICollectionView、它的布局、单元格和它的标题视图的代码:

  1. 创建 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"];
            }
    
  2. 创建自定义布局

        @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;
        }
    
  3. 单元格的数据源方法(在 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;
            }
    
  4. 补充标题视图的数据源方法(在 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;
            }
    

简而言之,当我尝试重新加载集合视图或集合视图的组件时,似乎没有调用补充标题视图的数据源方法。但是,我确实看到在自定义布局类中为补充视图创建属性的方法被调用了。如果有人能指出发生这种情况的任何可能原因,我将不胜感激!

4

1 回答 1

0

reloadItemsAtIndexPaths仅用于重新加载单元格。您可以通过使用 重新加载部分来重新加载补充视图reloadSections:。如果您仍然有问题,请在问题中包含您的NSFetchedResultsControllerDelegate实施。

于 2013-10-16T17:35:38.693 回答