UICollectionView DataSource 方法未在 CoreData 更改时调用
Posted
技术标签:
【中文标题】UICollectionView DataSource 方法未在 CoreData 更改时调用【英文标题】:UICollectionView DataSource Method not called on CoreData Change 【发布时间】:2013-10-16 17:14:57 【问题描述】:我有一个 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;
简而言之,当我尝试重新加载集合视图或集合视图的组件时,补充标题视图的数据源方法似乎没有被调用。但是,我确实看到在自定义布局类中为补充视图创建属性的方法被调用了。如果有人能指出任何可能的原因,这可能是 发生,我将不胜感激!
【问题讨论】:
【参考方案1】:reloadItemsAtIndexPaths
仅用于重新加载单元格。您可以通过使用reloadSections:
重新加载该部分来重新加载补充视图。如果您仍有问题,请在问题中包含您的 NSFetchedResultsControllerDelegate
实施。
【讨论】:
以上是关于UICollectionView DataSource 方法未在 CoreData 更改时调用的主要内容,如果未能解决你的问题,请参考以下文章
如何滚动另一个 UICollectionView 下方的 UICollectionView?
UICollectionView 单元内部已加载,但 UICollectionView 未显示
UICollectionView 断言失败 -[UICollectionView _updateWithItems:tentativelyForReordering:]
UITableviewCell 中的 UICollectionView。添加约束后,UICollectionView 不显示