2011-01-09 2 views
8

искал высоко и низко для этого:Основные данные: прерывание выполнения NSFetchRequest

В основных данных, есть способ прерывания/стоп/отмена и исполнение NSFetchRequest?

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

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

ответ

2

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

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

2

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

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

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

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

+2

Последнее не работает, потому что для упорядоченного запроса требуется почти столько же времени, чтобы получить первые 20 в качестве первого n. – mclin

1

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

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

И использовать этот код:

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

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

14

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

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

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

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

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

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

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

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

+0

Блестяще, спасибо! – JOM

+0

Вы также должны «Хит диск», если какой-либо символ был вставлен в текст поиска. Например, пользователь может ввести «fooar», а затем исправить его, вставив отсутствующий символ, а затем следующий поиск будет «foobar». – Sean

Смежные вопросы