NSFetchedResultsController: перемещенные объекты иногда сообщали как обновленные
В некоторых ситуациях, экземпляре NSFetchedResultsController могут сообщить перемещенные объекты с помощью a NSFetchedResultsChangeUpdate уведомление изменения вместо NSFetchedResultsChangeMove.
Выбранный контроллер результатов только отправляет объектные уведомления изменения, тегированные как NSFetchedResultsChangeMove когда исходный индексный путь отличается от нового индексного пути. Возможно, что серия объектных изменений может привести к перемещаемому объекту (такому как перемещение в новый раздел), все же его относительный индексный путь остается тем же (если другие объектные изменения произошли в объектах, появляющихся перед перемещенным объектом). Этот сценарий приведет к a NSFetchedResultsChangeUpdate уведомление, отправляемое делегату.
Возможное обходное решение должно поддержать дополнительное (не смоделированный) переменная экземпляра в Вашем объекте, указывающем, когда объект изменил раздел (вследствие изменения в его свойстве, определяющем раздел). Например, Вы могли бы объявить пользовательский класс следующим образом:
@interface MyClass : NSManagedObject |
{ |
BOOL _changedSection; |
} |
// The modeled property that determines the object's section. |
@property (nonatomic, retain) NSString *theSectionKey; |
// The unmodeled property that tracks if a section was recently changed. |
@property BOOL changedSection; |
@end |
Соответствующая реализация могла бы быть:
@synthesize changedSection=_ changedSection; |
- (void)setTheSectionKey:(id)value |
{ |
if (value != theSectionKey) { |
changedSection = YES; |
} |
[self willChangeValueForKey:@"theSectionKey"]; |
[self setPrimitiveTheSectionKey:value]; |
[self didChangeValueForKey:@"theSectionKey"]; |
} |
Можно тогда использовать это свойство, чтобы определить, отметило ли изменение как NSFetchedResultsChangeUpdate должен фактически быть обработан как a NSFetchedResultsChangeMove путем реализации controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: как проиллюстрировано в этом примере:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { |
UITableView *tableView = self.tableView; |
// This is the workaround. |
MyClass *myInstance = (MyClass *)anObject; |
if ( (NSFetchedResultsChangeUpdate == type) && ([myInstance changedSection]) ) { |
[myInstance setChangedSection:NO]; |
type = NSFetchedResultsChangeMove; |
newIndexPath = indexPath; |
} |
switch(type) { |
case NSFetchedResultsChangeInsert: |
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; |
break; |
case NSFetchedResultsChangeDelete: |
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; |
break; |
case NSFetchedResultsChangeUpdate: |
[self configureCell:(ExpenseCell *)[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; |
break; |
case NSFetchedResultsChangeMove: |
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; |
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; |
break; |
} |
} |
Copyright © 2015 Apple Inc Все права защищены. Условия использования | Политика конфиденциальности | обновленный: 09.10.2009