【问题标题】:Updating a UICollectionView when an item is added (Core Data), stuck on insertItemsAtIndexPaths添加项目时更新 UICollectionView(核心数据),卡在 insertItemsAtIndexPaths
【发布时间】:2014-09-12 19:55:58
【问题描述】:

好的,我真的被困在这里了:/在 Apple 的 Collection View Programming Guide for inserting an item 中说有两个步骤:

  1. 更新数据源对象中的数据。
  2. 调用集合视图的适当方法来插入或删除部分或项目。

我被第二个卡住了。我希望新项目出现在集合视图的开头。我不知道该为 insertItemsAtIndexPaths: 参数添加什么。我知道它需要一个索引对象数组,但我不知道如何告诉它选择集合的开始作为它的索引值,并且我也很困惑如何告诉它其他任何东西。您可以在我之前的代码 (cellForItemAtIndexPath) 中看到,我在填充集合时正在修改单元格内按钮元素的属性。如果我想在创建时修改新项目,我该怎么做?我非常感谢您对此提供的任何帮助,我觉得我在这里错过了很多东西并且真的碰壁了。

@implementation RepsCollectionViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        NSLog(@"Error : %@", error);
        abort();
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Collection view data source

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> secInfo = [self.fetchedResultsController.sections objectAtIndex:section];

    return [secInfo numberOfObjects];
}

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

    RepCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

    Rep *rep = [self.fetchedResultsController objectAtIndexPath:indexPath];

    cell.repButton.pressed = [rep.completed boolValue];
    cell.repButton.indexPath = indexPath;

    return cell;
}

#pragma mark - Fetched Results Controller

-(NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Rep" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"dateTimeCreated" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];

    _fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];

    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

#pragma mark - IBActions

- (IBAction)addRep:(id)sender {

    [NSEntityDescription insertNewObjectForEntityForName:@"Rep" inManagedObjectContext:self.managedObjectContext];

    [self.collectionView performBatchUpdates:^{

        [self.collectionView insertItemsAtIndexPaths:WHAT TO PUT HERE?];

    } completion:nil];
}

【问题讨论】:

    标签: ios core-data uicollectionview collectionview


    【解决方案1】:

    您似乎没有实现任何NSFetchedResultsControllerDelegate 方法。对于您想要的功能,作为获取结果控制器的代表是关键。

    NSFetchedResultsController 的实例将通知它的委托对匹配其获取请求的对象集合的更改。它通过在其委托上调用各种NSFetchedResultsControllerDelegate 方法来实现。例如,如果将一个新对象插入到分配给与获取请求匹配的获取结果控制器的NSManagedObjectContext 中,则会调用以下NSFetchedResultsControllerDelegate 方法:

    controllerWillChangeContent:

    controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:

    controllerDidChangeContent:

    controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: 是您在集合视图上调用insertItemsAtIndexPaths: 方法的地方,告诉它新项目在其数据源中可用。这看起来像:

    - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
        UICollectionView *collection = self.collectionView;
        switch(type) {
                    case NSFetchedResultsChangeInsert:
                    [collection insertItemsAtIndexPaths:@[newIndexPath] ];
                    break;
        }
    }
    

    显然,一个真实的例子应该正确地处理其他变化类型,这只是一个说明性的例子。您还应该实现其他NSFetchedResultsControllerDelegate 方法。不需要使用批量更新来更改集合视图,并且可以轻松实现。

    【讨论】:

    • 例如,如果添加了多个对象,这将导致崩溃。
    • 平息,非常感谢您抽出宝贵时间给出如此详细的答案。我试过这个 - 到目前为止只是为了 NSFetchedResultsChangeInsert 选项 - 它就像一个魅力!我将在周末之后添加所有委托方法的其余要求,并将在将来使用此方法更新集合视图。感激不尽!
    【解决方案2】:

    我也没有正确理解您的问题。但这会对你有所帮助,

    从 Core Data 获取所有数据后,

    [self.collectionView reloadData];
    

    在此之前将所有数据放到self.fetchedResultsController

    【讨论】:

    • 嗨 BC_Dilum,当我尝试这样做时,应用程序在触发操作时崩溃:“无效更新:第 0 部分中的项目数无效。”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多