Отмена NSJSONSerialization — поиск по мере ввода, запросы перекрываются

Подобно функции поиска приложения Facebook для iPhone, я реализую поиск по мере того, как вы вводите функциональность в свое приложение, хотя у меня есть проблема при декодировании данных в формат JSON.

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

Я установил NSLOG после каждого декодирования с использованием NSJSONSerialization для ключевого слова «промышленность».

2013-04-09 23:38:18.941 Project Name [42836:1d03] http://fooWebAddress/json/?method=search&limit=10&q=indus
2013-04-09 23:38:19.776 Project Name [42836:3e07] http://fooWebAddress/json/?method=search&limit=10&q=indu
2013-04-09 23:38:20.352 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=indust
2013-04-09 23:38:21.814 Project Name [42836:4e03] http://fooWebAddress/json/?method=search&limit=10&q=industr
2013-04-09 23:38:23.434 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=ind
2013-04-09 23:38:24.070 Project Name [42836:7503] http://fooWebAddress/json/?method=search&limit=10&q=industry

Как видите, все не в порядке.

Есть ли у кого-нибудь способ остановить NSJSONSerialization для предыдущего соединения. Или, возможно, какой-либо другой способ решить эту проблему?


Шаги до NSJSONSerialization...

  1. NSURLRequest (инициализация с URL-адресом)
  2. NSOperationQueue
  3. NSURLConnection (асинхронный)
  4. NSJSONСериализация

Заранее спасибо.


person Scott McConnell    schedule 09.04.2013    source источник
comment
Отменяете ли вы предыдущие операции (если да, то как)?   -  person A-Live    schedule 09.04.2013
comment
просто подождите, пока пользователь перестанет печатать, а затем вызовите только веб-службу. Между тем, если пользователь постоянно печатает, отмените предыдущий запрос на вызов веб-службы, используя приведенный ниже код. [NSObject cancelPerformSelectorsWithTarget:self]; [самостоятельный селектор:@селектор(sendSearchRequest) withObject:searchText afterDelay:0.1f];   -  person Wolverine    schedule 22.12.2015


Ответы (4)


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

Вы можете сделать это, поддерживая своего рода ссылку lastRequest или lastOperation. Когда пользователь начнет печатать, вызовите [self.lastRequestOrOperation cancel] и проигнорируйте любые дальнейшие уведомления от этого запроса с проверкой, подобной if (request != self.lastRequest) { return; }, в любых обратных вызовах, которые у вас есть.

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

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

person Mike Weller    schedule 09.04.2013

Это гораздо более сложная проблема, чем просто возможность отменить NSJSONSerialization. Я предлагаю использовать NSFetchedResultsController для заполнения вашего табличного представления, которое показывает результаты поиска. Используйте поисковый термин как одну из переменных предиката в NSFetchRequest, прикрепленном к NSFetchedResultsController. А затем, когда вы анализируете результаты с помощью NSJSONSerialization, сохраните результаты с условием поиска, связанным с этим запросом. Как только условие поиска изменилось (что вы можете обнаружить, когда пользователь вводит больше символов), повторно создайте NSFetchedResultsController и перезагрузите табличное представление. Кроме того, вы также можете попробовать отменить вызов для разбора предыдущих результатов, если вы запустили его с помощью PerformSelector:withObject:afterDelay. Имейте в виду, что на это нельзя всегда полагаться, поскольку вызов мог быть инициирован к тому времени, когда вы пытаетесь отменить его.

person sixthcent    schedule 09.04.2013

Вроде базовый, но вы всегда можете поддерживать nsdictionary подклассов NSURLRequests (подклассы для предоставления тега).

Стартовый запрос — добавить запрос в индикатор с тегом = array.count — 1, с ключом, совпадающим с тегом Connection return — это самый последний запрос, если да, разобрать json Parse JSON — это самый последний запрос, если да, показать результаты, если нет, отображать только в том случае, если предыдущие результаты не отображались. Обработка запроса - удалить ключ из словаря.

последний запрос = содержит ли словарь объект с более высоким значением ключа

person user352891    schedule 09.04.2013

В настоящее время вы вводите каждый символ и вызываете веб-службу. Зачем вызывать веб-сервис на каждую набранную букву. Если пользователь печатает непрерывно, это увеличит нагрузку, поэтому вызывайте веб-сервис только тогда, когда пользователь останавливается на определенный интервал времени. а затем передайте эту строку для вызова веб-службы или любого метода, который вы вызываете.

[NSObject cancelPerformSelectorsWithTarget:self]; // This will cancel your all req which is going to make when user typing without stopping 
[self performSelector:@selector(sendSearchRequest) withObject:searchText afterDelay:0.1f]; // This will pass the string to call a web-service method, on which user hold for some time.
person Wolverine    schedule 22.12.2015