简体   繁体   中英

Updating a UICollectionView when an item is added (Core Data), stuck on insertItemsAtIndexPaths

Ok, I'm really stuck here :/ In Apple's Collection View Programming Guide for inserting an item it says there are two steps :

  1. Update the data in your data source object.
  2. Call the appropriate method of the collection view to insert or delete the section or item.

I am stuck on the second one. I want the new item to appear at the start of the collection view. I do not know what to put for the insertItemsAtIndexPaths: argument. I know that it wants an Array of index objects, but I do not know how to tell it to choose the start of the collection as it's index value and am also confused how to tell it anything else. You can see in my earlier code (cellForItemAtIndexPath) I am modifying the properties of a button element within the cell upon populating the collection. If I wanted to modify the new item upon creation, how would I do that? I really appreciate any help on this, I feel I am missing a lot here and am really hitting a brick wall.

@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];
}

You don't seem to have implemented any of the NSFetchedResultsControllerDelegate methods. For the functionality you want, being the delegate of the fetched results controller is key.

An instance of NSFetchedResultsController will inform it's delegate of changes to the collection of objects that match it's fetch request. It does so by calling the various NSFetchedResultsControllerDelegate methods on it's delegate. For example, if a new object is inserted into the NSManagedObjectContext assigned to the fetched results controller that matches the fetch request, the following NSFetchedResultsControllerDelegate methods are called:

controllerWillChangeContent:

controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:

controllerDidChangeContent:

controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: is where you would call the insertItemsAtIndexPaths: method on the collection view, to tell it that new items were available in it's data source. This would look like:

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

Obviously, a real example should correctly handle the other change types, this is just an illustrative example. You should also implement the other NSFetchedResultsControllerDelegate methods. Using batch updates for collection view changes is not required and can be implemented easily.

I also don't understand your question correctly. But this will help you,

After fetching all the data from Core Data,

[self.collectionView reloadData];

Before that put all the data to self.fetchedResultsController

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM