Основные данные: Прерывание, выполняющее NSFetchRequest - PullRequest
9 голосов
/ 09 января 2011

В поисках максимума и минимума для этого:

В Core Data есть ли способ прервать / остановить / отменить и выполнить NSFetchRequest?

Я реализую добавочный поиск вПриложение для iPhone, и я попробовал все способы его оптимизации, но этого недостаточно (у меня 42 000 записей), поэтому я должен запустить его в NSOperation.Когда набирается новый символ, мне нужно отменить предыдущий fetchRequest, но [nsoperation cancel] ничего не делает.

Другой подход может состоять в том, чтобы переместить поле, которое я ищу, в какой-то другой прерываемый индекс, возможно, в память, или, возможно, в отдельную базу данных sqlite3, которая, как представляется, прерываема с sqlite_interrupt.

Ответы [ 4 ]

14 голосов
/ 20 декабря 2013

Прямой ответ на ваш вопрос - нет. Наилучшим вариантом с вашей текущей конструкцией является выполнение их в действии, но тогда у вас есть барьер для потоков, о котором нужно беспокоиться и который замедляет работу. Имейте в виду, что если ваши операции не выполняются в главном потоке, то вам нужна отдельная NSManagedObjectContext для операции, или вы столкнетесь с проблемами потоков.

Лучший вопрос: Почему вы делаете новую выборку для каждого персонажа?

Если у вас уже есть результаты выборки из предыдущего поиска, и пользователь не удалил символ, просто возьмите существующие результаты и запустите свой предикат против NSArray. Это дополнительно улучшит поиск вместо того, чтобы идти на диск каждый раз. Поскольку он находится в памяти, он будет очень быстрым.

При реализации поля поиска учитывайте следующие параметры:

  • Хит диска только по первому символу
  • Хит диска, только если символ удален из поля поиска
  • Рассмотрите возможность предварительной загрузки objectID и свойства для поиска, чтобы избежать попаданий на диск.

В зависимости от того, что вы ищете (и есть способы перенормировать хранилище базовых данных для улучшения поиска), вы можете предварительно загружать в память немного. Даже с 42K записями, если свойства поиска достаточно малы, вы можете загрузить их все в память.

Скорее всего, вам все равно нужно проверить этот вариант использования, если пользователь начинает с нажатия "A".

Какая часть NSFetchRequest медленная? Попадание в базу данных SQLite или загрузка данных в память? Исходя из своего ответа, вы можете улучшить эффективность поиска напрямую.

3 голосов
/ 06 июня 2011

Мое решение состояло в том, чтобы позволить операциям запроса продолжаться, но проверить, были ли они отменены перед отправкой события для обновления пользовательского интерфейса.

Это не идеально, потому что у вас все еще может быть запущено много операций с запросами, результаты для которых никогда не будут использоваться, но все равно это будет немного быстрее.

2 голосов
/ 20 декабря 2013

У меня фактически была та же проблема, что и у вас. Для ее решения я использую performSelector:afterDelay: метод

Это немного сложно, но когда пользователь быстро набирает 3 быстрых буквы, я не хочу отправлять 3 запроса, а только один, когда пользователь заканчивает ввод. Я установил небольшую задержку 0,5 или более.

И используйте этот код:

[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self performSelector:@selector(fetchSearch:) withObject:searchQuery afterDelay:0.5];

Если пользователь печатает быстро, он отменяет предыдущие запросы и отправляет только последний.

2 голосов
/ 09 января 2011

Краткий ответ - нет, не напрямую, извините.

Длинный ответ - Да, но вы должны сделать немало или потрудиться, чтобы сделать это

Вам нужно будет запустить его в фоновом потоке (что звучит так, как будто вы уже это делаете через NSOperation)

В вашей выборке установите лимит, чтобы получать 20 результатов одновременно, и запустите его в цикле. Каждый раз в цикле добавляйте полученные результаты в массив. Каждый раз, когда выборка получает каждый набор результатов, проверьте, хотите ли вы отменить запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...