Основные данные: фоновая выборка, NSFetchedResultsController и время сортировки - PullRequest
8 голосов
/ 14 апреля 2011

Проблема, с которой я сталкиваюсь, заключается в следующем:

У меня есть UITableView, который я загружаю данными из NSFetchedResultsController, который извлекает около 6000 строк из основных данных.fetchBatchSize из NSFetchRequest установлено в 20, и если я не применяю NSSortDescriptor, выборка будет достаточно быстрой, чтобы не блокировать поток пользовательского интерфейса.

Однако мне нужно отобразить эти строкиотсортировано в алфавитном порядке, для которого я использую следующий NSSortDescriptor:

[[[NSSortDescriptor alloc] initWithKey:@"optionText" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];

И вот, когда все меняется, операция извлечения теперь занимает около 3 секунд, потому что сортируется 6000 строк.Очевидно, что в течение этих секунд пользовательский интерфейс блокируется, и пользовательский интерфейс ужасен.

Я знаю, что могу выполнить выборку в фоновом потоке, а затем передать идентификаторы объектов в основной поток, но в этом случае как можноЯ все еще использую NSFetchedResultsController в основном потоке (я также использую его для наблюдения за изменениями в данных)?

У меня также есть indexed атрибут, по которому я сортирую, но это только оптимизирует внешний вид.ups и не сортировка производительности.

Любые идеи будут высоко оценены, спасибо!

Ответы [ 6 ]

3 голосов
/ 13 сентября 2011

Как насчет использования свойства batchSize NSFetchRequest?

Если вы установите ненулевой размер пакета, коллекция объектов, возвращаемых при выполнении выборки, разбивается на пакеты.Когда выборка выполняется, весь запрос оценивается, и идентификаторы всех соответствующих объектов записываются, но не более, чем данные объектов batchSize, будут извлекаться из постоянного хранилища за один раз.Массив, возвращаемый при выполнении запроса, будет прокси-объектом, который прозрачно сбрасывает пакеты по требованию.(В терминах базы данных это курсор в памяти.)

1 голос
/ 19 сентября 2011

Я выполняю фоновые импортные операции в NSOperation, который использует отдельный NSManagedObjectContext. Периодически я сохраняю второй контекст, который запускает уведомление для обновления моего основного NSManagedContext, к которому подключен мой NSFetchedResultsController.

Может быть, аналогичная техника может быть применена к вашей выборке

Вот какао, это статья моей подруги об этом:

http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/

и метод также упоминается в руководстве по программированию основных данных «Импорт в пакетах»

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174-SW1

0 голосов
/ 17 ноября 2012

Прежде всего, NSFetchedResultsController обычно используется в основном потоке.И до сих пор он не поддерживает фоновую выборку. Apple выпустила iOS 6.

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

(Насколько я помню, вы должны установить дескриптор сортировки в NSFetchedResultController. Поэтому я не уверен, как вы заставили его работать, не устанавливая дескриптор сортировкивзгляните на ссылку на класс)

Я не уверен, используете ли вы Sqlite Store.Если так, я вряд ли могу поверить в твою работу с дескриптором.(взгляните на Руководство по программированию Core Data: раздел устранения неисправностей).Если нет, хранить такое количество данных в памяти было бы не очень хорошей идеей

Наконец мы достигли точки, почему это медленно.Такая сортировка с использованием «localizedCaseInsensitiveCompare:» замедляет выборку, так как сравнение строки Unicode будет медленным.(упоминается в WWDC 2010 Core Data Performance на iPhone).

Как и во многих других приложениях, вы должны создать строковое поле / свойство не-Unicode на основе вашего "optionText" и сортировать на основе этой строки не-Unicodeимущество.

0 голосов
/ 11 августа 2011

Отображение 6000 строк в одной таблице может быть не лучшим решением с точки зрения пользовательского опыта. Может быть, вы должны добавить таблицу фильтров раньше. Похоже на группы в адресной книге. Возможно, это поможет улучшить взаимодействие с пользователем, если вам удастся уменьшить количество строк на один параметр фильтра до более управляемого числа. Это уменьшит время загрузки и время на прокрутку.

Я не знаю, какие данные вы отображаете, поэтому, возможно, нет другого способа, кроме как отобразить все в одном длинном списке. Для людей вы можете добавить варианты для пола и возрастных групп. Для автомобилей вы можете добавить фильтр по марке и модели ....

0 голосов
/ 11 августа 2011

Использование кеша, вероятно, поможет повысить производительность.

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

0 голосов
/ 14 мая 2011

Вы пытались запустить метод executeFetch: в фоновом режиме, либо с помощью

[controller performSelectorInBackground:@selector(performFetch) withObject:nil];

или

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    [controller performFetch];
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...