Основные данные: executeFetchRequest vs performFetch

Мне нужен подробный список сравнения между ними. Вещи, которые я знал:

executeFetchRequest:

  • Сообщение отправлено в MOC
  • Возвращает массив управляемых объектов
  • Цель: выбор объектов из постоянного хранилища в MOC
  • С представлением таблицы: не имеет никакого отношения к представлению таблицы
  • Частота: часто используется в цикле, поэтому ее можно было бы назвать много раз

performFetch:

  • Сообщение отправлено в FRC
  • После его вызова используйте fetchedObjects для возврата массива управляемых объектов
  • С табличным представлением: FRC специально предназначен для хранения управляемых объектов и табличных таблиц в синхронизации, и используйте performFetch для инициализации этого процесса.
  • Частота: часто только один раз. Если запрос на выборку FRC не требуется, не нужно вызывать performFetch второй раз

Пожалуйста, поправьте меня, если я ошибаюсь и добавлю список. Спасибо.

Ответ 1

О executeFetchRequest:

Сообщение, отправленное в MOC

Да

Возвращает массив управляемых объектов

Да, но вы также можете изменить тип результатов, которые хотите получить. В NSFetchRequest вы можете установить другой тип результата с помощью:

- (void)setResultType:(NSFetchRequestResultType)type

где NSFetchRequestResultType могут быть разных типов. Взято из документа Apple:

enum {
   NSManagedObjectResultType        = 0x00,
   NSManagedObjectIDResultType      = 0x01,
   NSDictionaryResultType           = 0x02
   NSCountResultType                = 0x04
};
typedef NSUInteger NSFetchRequestResultType; 

Цель: выбор объектов из постоянного хранилища в MOC

Да, создав NSFetchRequest и выполнив запрос, он будет таким же, как создание инструкции SELECT в SQL. Если вы также используете NSPredicate то же самое, что и оператор SELECT-WHERE.

С представлением таблицы: не имеет ничего общего с представлением таблицы

Да, но с полученными данными вы можете заполнить таблицу

Частота: часто используется в цикле, поэтому ее можно было бы назвать много раз

Это зависит от того, чего вы хотите достичь. Он может быть в цикле или нет. Выполнение запроса в цикле может повлиять на производительность, но я бы не стал беспокоиться об этом. Под капотом Core Data поддерживает своего рода механизм кэширования. Каждый раз, когда вы выполняете запрос, если данные не находятся в кеше, Core Data выполняет обратную поездку в ваш магазин (например, файл sql) и заполняет кеш объектами, которые он извлек. Если вы выполняете один и тот же запрос, поездка туда и обратно не будет выполняться снова из-за механизма кэширования. В любом случае, вы могли бы избежать выполнения запроса в цикле выполнения, просто перемещая этот запрос за пределы цикла.

О performFetch:

Сообщение, отправленное в FRC

Да

После вызова, используйте fetchedObjects, чтобы вернуть массив управляемых Объекты

Да, но вы также можете получить объект с помощью [_fetchedResultsController objectAtIndexPath:indexPath];, если вы заполняете определенную ячейку в таблице.

Здесь я действительно рекомендую прочитать хороший учебник по NSFetchedResultsController

С табличным представлением: FRC предназначен специально для хранения управляемых объектов и таблицы таблицы в синхронизации, и используйте функцию executeFetch для инициализации этого процесс.

Да, NSFetchedResultsController работает в комбинации с NSManagedObjectContext для вас. Кроме того, он обеспечивает ленивую загрузку данных. Предположим, у вас есть 1000 элементов, которые вы извлекаете, и вы хотите отобразить их в UITableView. Установка запроса для NSFetchRequest как:

[fetchRequest setFetchBatchSize:20];

и используя его с экземпляром NSFetchedResultsController, он позволяет сначала загрузить 20 элементов. Затем, когда вы прокручиваете, загружаются 20 других элементов и так далее. Без NSFetchedResultsController вы должны реализовать это поведение вручную. Обратитесь к руководству, которое я предоставил для дальнейшей информации.

Частота: часто только один раз. Если запрос выборки FRC не изменяется, нет необходимо вызвать функцию executeFetch во второй раз

Это зависит от того, чего вы хотите достичь. Большую часть времени вы можете позвонить ему один раз.

Надеюсь, что это поможет.

Edit

Вы должны явно называть performFetch. Мне нравится создавать свойство для NSFetchedResultsController в моем файле заголовка (.h), например

@property (nonatomic, strong, readonly) NSFetchedResultsController* fetchedResultsController;

и синтезируйте его в файле реализации (.m), например

@synthesize fetchedResultsController = _fetchedResultsController;

Затем всегда внутри файла .m переопределяет getter для создания нового экземпляра:

- (NSFetchedResultsController*)fetchedResultsController
{
    // it already exists, so return it
    if(_fetchedResultsController) return _fetchedResultsController;

    // else create it and return

    _fetchedResultsController = // alloc-init here with complete setup

   return _fetchedResultsController;
}

Как только вы закончите, внутри вашего класса (например, в методе viewDidLoad) используйте его как

NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {

    // Handle the error appropriately.
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}

Ответ 2

Вы сравниваете неправильные элементы. NSFetchedResultsController использует NSManagedObjectContext для выполнения выборки и при правильной конфигурации отслеживает изменения в контексте управляемого объекта, чтобы проверить состояние свойств выборки, которые он контролирует, но фактические выборки выполняются контекстом. В обоих случаях NSManagedObjectContext выполняет выборку. Разница заключается в том, что, используя NSManagedObjectContext напрямую, вы получаете объект типа NSArray (фактический класс выполнения отличается от массива, который вы используете с помощью [NSArray array]), тогда как NSFetchedResultsController имеет другую цель (имеет набор результаты и отслеживать изменения записей и объектов по запросу на выборку). Другими словами, NSFetchedResultsController работает с использованием контекста, но он отличается от простого набора объектов.

Одно замечание: вы не должны использовать executeFetchRequest внутри цикла, особенно называя его "много раз". Каждая выборка имеет свои эксплуатационные расходы. Вы можете вызвать executeFetchRequest один раз и выполнить цикл, чтобы проверить результат.