Метод UICollectionView DataSource не вызывается при изменении CoreData

У меня есть 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. Метод DataSource для ячеек (вызывается в обновлениях компакт-диска)

            - (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;
            }
    

Короче говоря, когда я пытаюсь перезагрузить представление коллекции или компоненты представления коллекции, метод источника данных для дополнительных представлений заголовков не вызывается. Однако я вижу, что вызывается метод создания атрибутов для дополнительного представления в пользовательском классе макета. Если кто-то может указать любую возможную причину, по которой это может происходить, я был бы признателен!




Ответы (1)


reloadItemsAtIndexPaths предназначен только для перезагрузки ячеек. Вы можете перезагрузить дополнительный вид, перезагрузив раздел с помощью reloadSections:. Если у вас все еще есть проблемы, пожалуйста, укажите свою реализацию NSFetchedResultsControllerDelegate в вопросе.

person Timothy Moose    schedule 16.10.2013