Получить indexPath объекта Core Data в UITableView

У меня есть UITableView, который я заполняю из основных данных с помощью следующего NSfetchedResultsController:

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

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:_managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

У меня есть другой метод, прикрепленный к кнопке «Добавить», который добавляет новый элемент основных данных в базу данных. Как только объект добавлен, моя таблица обновляется должным образом, и новый объект отображается в правильном месте в соответствии с сортировкой «дата» в извлеченном контроллере результатов. Мой новый объект добавляется с использованием сегодняшней даты для его атрибута «дата». Я добавляю объект следующим образом:

NSManagedObject *newEvent = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];
[newEvent setValue:@"New Client" forKey:@"name"];
[newEvent setValue:[NSDate date] forKey:@"date"];
NSError *error;
    if (![context save:&error]) {
        NSLog(@"Core Data error!  Could not save: %@", [error localizedDescription]);
    }

Теперь, как часть моего метода «Добавить», мне нужно выбрать строку, в которую был добавлен новый элемент, и перейти к экрану редактирования. Очевидно, что в зависимости от других дат элементов в таблице это может быть где угодно.

Я хочу выбрать это так, но у меня нет indexPath:

[self.eventListTable selectRowAtIndexPath:indexPath animated:YES  scrollPosition:UITableViewScrollPositionBottom];

Как определить, в какой строке (indexPath) был добавлен мой новый объект, чтобы я мог правильно выбрать его?

Спасибо!


person Kent    schedule 10.03.2014    source источник


Ответы (2)


NSFetchedResultsController есть метод с именем: indexPathForObject:

Если вы вставили элементы во время обработки изменений (методы делегата FRC), выберите самый последний вставленный элемент. вы можете определить индексный путь объекта, используя описанный выше метод.

Или вы можете сохранить вставленный объект из вашей последней вставки, а в методе делегата didChangeContent выбрать вставленный элемент и обнулить сохраненную вами переменную (чтобы дальнейшие вызовы не запускали переход).

person Dan Shelly    schedule 10.03.2014
comment
Итак, как это тогда? Добавьте метод в мой метод AddItem и назначьте ему ivar, затем в методе делегата didChangeContent, если ivar существует, используйте indexPathForObject для выбора и обработки строки и обнуления ivar. Если ivar уже был нулевым (потому что изменение было от редактирования или удаления), просто ничего не делайте. Это то, что вы имеете в виду? - person Kent; 10.03.2014
comment
точно! (остерегайтесь вставок из других источников, таких как веб-синхронизация и т. д.) - person Dan Shelly; 10.03.2014
comment
Спасибо! Я попробую это! - person Kent; 10.03.2014

Вам нужно будет найти объект в вашем NSFetchedResultsController, чтобы разрешить его indexPath. Однако для этого вам нужно дождаться, пока ваш NSFetchedResultsController распознает объект. Вероятно, вам придется дождаться срабатывания методов обратного вызова делегата из NSFetchedResultsController, а затем использовать -indexPathForObject:, чтобы разрешить его обратно в indexPath, а затем выбрать строку.

Визуально все должно работать идеально. Строка появится, а затем будет выбрана.

person Marcus S. Zarra    schedule 10.03.2014
comment
Какой метод обратного вызова? изменил содержимое? - person Kent; 10.03.2014
comment
Вы определенно можете сделать это там после того, как выпустите UITableVIew для обновления. - person Marcus S. Zarra; 10.03.2014
comment
Если не сделалChangeContent, то какие еще есть варианты? - person Kent; 10.03.2014
comment
Существует также -controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:, который срабатывает для каждой новой добавляемой строки и уже имеет indexPath. Вы также можете попробовать положить его туда. - person Marcus S. Zarra; 10.03.2014
comment
Я только что заметил -controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:, где я уже наблюдаю за «NSFetchedResultsChangeInsert» и вставляю строку в таблицу с insertRowsAtIndexPath. В этот момент у меня уже есть indexPath к объекту. Могу я просто сделать это: [self.eventListTable selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom]; здесь? (Я не могу проверить прямо сейчас.) - person Kent; 10.03.2014
comment
Я тоже не могу проверить ваш код :) Попробуйте и посмотрите, что получится. - person Marcus S. Zarra; 10.03.2014
comment
Ха-ха! Я обязательно буду. За свой недолгий опыт работы с iOS я обнаружил, что есть много мест, куда можно поместить вещи, которые вроде бы работают, но не являются лучшим выбором из-за других разветвлений. Вечером протестирую! - person Kent; 10.03.2014