Хорошо, я провожу последние 8 часов, читая каждый пример.
Я пришел к выводу, что мне придется сделать некоторый код «Доказательство концепции», чтобы увидеть, возникнет ли даже проблема со скоростью при создании нового потока для «каждого» нажатия клавиши.
Оказывается, что использование NSOperation и NSOperationQueue более чем адекватно, как с точки зрения скорости, так и особенно с точки зрения простоты и абстракции.
Вызывается после каждого нажатия клавиши:
- (void) searchFieldChanged:(UITextField*) textField {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSString *searchString = textField.text;
if ([searchString length] > 0) {
[self performSelector:@selector(doSearch:) withObject:textField.text afterDelay:0.8f];
}
}
Это в основном для остановки формы кода, запускающей поиск нажатий клавиш, которые менее 800 мс. Кроме.
(Я бы сказал, что намного ниже, если бы не маленькая сенсорная клавиатура).
Если время ожидания истекло, время искать.
- (void) doSearch:(NSString*) searchString {
[queue cancelAllOperations];
ISSearchOperation *searchOperation = [[ISSearchOperation alloc] initWithSearchTerm:searchString];
[queue addOperation:searchOperation];
[searchOperation release];
}
Отменить все операции, которые в данный момент находятся в очереди. Это вызывается каждый раз, когда новый поиск
запущен, он гарантирует, что операция поиска, которая уже выполняется, упорядоченно закрывается, а также гарантирует, что только 1 поток находится в состоянии «не отменено».
Реализация ISSearchOperation действительно проста:
@implementation ISSearchOperation
- (void) dealloc {
[searchTerm release];
[JSONresult release];
[parsedResult release];
[super dealloc];
}
- (id) initWithSearchTerm:(NSString*) searchString {
if (self = [super init]) {
[self setSearchTerm:searchString];
}
return self;
}
- (void) main {
if ([self isCancelled]) return;
[self setJSONresult:/*do webservice call synchronously*/];
if ([self isCancelled]) return;
[self setParsedResult:/*parse JSON result*/];
if ([self isCancelled]) return;
[self performSelectorOnMainThread:@selector(searchDataReady:) withObject:self.parsedResult waitUntilDone:YES];
}
@end
Существует два основных этапа: загрузка данных из веб-службы и анализ.
После каждой проверки я проверяю, был ли поиск отменен с помощью [NSOperationQueue cancelAllOperations]
, если он был выполнен, то мы возвращаемся, и объект хорошо очищается с помощью метода dealloc.
Мне, вероятно, придется установить какое-то время ожидания как для веб-службы, так и для синтаксического анализа, чтобы предотвратить засорение очереди объектом KIA .
Но сейчас это на самом деле молниеносно, в моем тесте я искал словарь из 16.000 записей и выводил Xcode NSLog на экран (приятно замедляет работу) каждые 800 мс. Я выдаю новую строку поиска через таймер и тем самым отменяю старую, прежде чем она закончит свои результаты NSLog для цикла экрана.
NSOperationQueue обрабатывает это без сбоев и не более нескольких мс. двух потоков выполняется. На пользовательский интерфейс не влияют вышеуказанные задачи, выполняющиеся в фоновом режиме.