从 UICollectionView 的 viewForSupplementaryElementOfKind 获取 NSFetchedResultsController 部分对象

Posted

技术标签:

【中文标题】从 UICollectionView 的 viewForSupplementaryElementOfKind 获取 NSFetchedResultsController 部分对象【英文标题】:Get NSFetchedResultsController section object from UICollectionView's viewForSupplementaryElementOfKind 【发布时间】:2013-10-26 14:03:34 【问题描述】:

我有一个名为Location 的数据模型。我将这些用作UICollectionViewController 中的部分标题。每个location 可以在这些部分内显示items。我想在viewForSupplementaryElementOfKind 中自定义我的部分标题。但我不知道如何从这个方法中接收正确的 Location 对象。

我尝试过这样的事情:

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView   viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath


    id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections] [indexPath.section];
    Item *item = sectionInfo.objects[0];
    Location *location = item.location;   
    SectionHeaderView *headerView = [collectionView   dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader   withReuseIdentifier:@"SectionHeader" forIndexPath:indexPath];
    headerView.label.text = location.name;
    [...]

但我不断得到:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM   objectAtIndex:]: index 0 beyond bounds for empty array'

这可能是因为位置可能没有任何项目。关于我应该如何做的任何其他想法?

【问题讨论】:

问题是否仅出现在没有项目的部分?换句话说,如果所有部分都不为空,您是否获得了正确的 Location 对象? 不,但是如果它没有任何物品并且我不能item.location,我不确定如何获得正确的位置。 实际上,我想知道当您使用上一个问题的答案中的设置时,您如何获得零项的部分。您的数据源或委托方法可能存在问题。但我不确定...... @MartinR 是的,你是对的。再次尝试使用断点,它已经在id &lt;NSFetchedResultsSectionInfo&gt; sectionInfo = [self.fetchedResultsController sections][indexPath.section]; 上崩溃。你认为我应该使用另一种方法吗? 【参考方案1】:

您的代码看起来很正确,并且在我的小型测试应用程序中按预期工作。 因此,我假设您在数据源方法中存在一些错误。

这是我用的:

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

    return [[self.frc sections] count];


-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

    id <NSFetchedResultsSectionInfo> sectionInfo = [self.frc sections][section];
    return [sectionInfo numberOfObjects];


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

    CellView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CellView" forIndexPath:indexPath];
    Item *item = [self.frc objectAtIndexPath:indexPath];
    cell.name.text = item.name;
    return cell;


-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

    id <NSFetchedResultsSectionInfo> sectionInfo = [self.frc sections][indexPath.section];
    Item *item = sectionInfo.objects[0];
    Location *location = item.location;
    HeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                                                withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];
    headerView.title.text = location.name;
    return headerView;

获取结果控制器的创建如下:

- (NSFetchedResultsController *)frc

    if (_frc == nil ) 
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Item"];
        NSSortDescriptor *sort1 = [[NSSortDescriptor alloc] initWithKey:@"location.name" ascending:NO];
        NSSortDescriptor *sort2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
        NSArray *sortDescriptors = @[sort1, sort2];
        [fetchRequest setSortDescriptors:sortDescriptors];

        _frc = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                   managedObjectContext:self.context
                                                     sectionNameKeyPath:@"location.name"
                                                              cacheName:nil];
        NSError *error;
        _frc.delegate = self;
        [_frc performFetch:&error];
    
    return _frc;

备注: 带有获取结果控制器的集合视图的自动更新 相当棘手,所以这篇文章

http://ashfurrow.com/blog/how-to-use-nsfetchedresultscontroller-with-uicollectionview

(带有代码示例)可能很有趣。

【讨论】:

谢谢,但这也意味着每个部分/位置必须至少有一个项目?看起来和我现在的很相似。你怎么看:github.com/timothyarmes/TAFetchedResultsController? @Anders:我的回答适用于“正常”FRC,它(据我所知)不能有空部分。我不知道您使用“特殊” FRC。我会看看那个项目,但可能不会在明天之前。 好的,很好。我还没用。但是想到这样做。让我知道你的想法! :) @Anders:我现在对你的实际问题有点困惑。如果您使用“正常”FRC 而不是 TAFetchedResultsController,那么上面的代码应该可以工作并且不会因异常而崩溃。至少它在我创建的一个小型测试应用程序中工作。 我想我找到了我的问题。我不小心使用了tableView numberOfSections 而不是collectionView。而且我还决定为每个位置创建一个默认项目,以便始终显示这些部分。

以上是关于从 UICollectionView 的 viewForSupplementaryElementOfKind 获取 NSFetchedResultsController 部分对象的主要内容,如果未能解决你的问题,请参考以下文章

在 UICollectionView 上与内容从右到左对齐

UI COLLECTION VIEW - 如何在 UICollectionView 上设置附件类型复选标记/披露者

Swift 探索 UICollectionView 之 SupplementaryView 和 Decoration View

Swift 探索 UICollectionView 之 SupplementaryView 和 Decoration View

uicollectionview下拉调用哪个方法

滑动 uicollectionview 时保持第一个可见 header view 的 uilabel 的 text color = yellow