UISearchBar определяет, когда пользователь останавливает тип, и не выполняет поиск сразу, поэтому обнаруживает паузу - PullRequest
17 голосов
/ 10 марта 2012

Я ищу реализацию UISearchbar, которая извлекает информацию из URL, и с методом по умолчанию:

 - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{

Я могу сразу определить, когда текст изменяется, и выполнить выборку URL-адреса, но при этом тип текста медленный, потому что iPhone ищет URL-адрес, поэтому я хочу начать выборку URL-адреса, когда пользователь остановлен. писать в течение некоторой секунды, поэтому я хочу обнаружить паузу набора текста, чтобы обновить табличное представление, получая информацию по URL. Я нашел более старый пост по этому запросу, и я попробовал решение, которое для меня не работает:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(request:)     object:searchText];

    //.....

    [self performSelector:@selector(request:) withObject:searchText afterDelay:1.5];
}

-(void)request:(NSString *)myString
{
    NSLog(@"%@",myString);
}

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

Ответы [ 2 ]

24 голосов
/ 10 марта 2012

Похоже, что предоставленное решение не работает, потому что аргумент "searchText" для cancelPreviousPerformRequestsWithTarget:selector:object: не соответствует аргументу "searchText" с предыдущим вызовом performSelector:withObject:afterDelay:; поэтому отложенные поиски ставятся в очередь при каждом изменении текста и никогда не отменяются.

Вы можете использовать NSTimer для отсрочки вызова поиска и отмены таймера при каждом изменении текста: присвойте своему объекту свойство или поле NSTimer; в searchBar:textDidChange: отмените любой существующий таймер, затем создайте и запланируйте новый. Цель таймера должна вызывать ваш метод поиска.

Что-то вроде (от макушки):

// in your class' .h object fields
{
  ...
  NSTimer *searchDelayer; // this will be a weak ref, but adding "[searchDelayer invalidate], searchDelayer=nil;" to dealloc wouldn't hurt
  ...
}

// in the .m

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
  [searchDelayer invalidate], searchDelayer=nil;
  if (YES /* ...or whatever validity test you want to apply */)
    searchDelayer = [NSTimer scheduledTimerWithTimeInterval:1.5
                                                     target:self
                                                   selector:@selector(doDelayedSearch:)
                                                   userInfo:searchText
                                                    repeats:NO];
}

-(void)doDelayedSearch:(NSTimer *)t
{
  assert(t == searchDelayer);
  [self request:searchDelayer.userInfo];
  searchDelayer = nil; // important because the timer is about to release and dealloc itself
}

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

[отредактировано, чтобы добавить:]

Вот как вы могли бы сделать это, если бы вы использовали использование cancelPreviousPerformRequestsWithTarget ...:

// in your class' .h object fields
{
  ...
  NSString *priorSearchText; // this will NOT be a weak ref, so adding "[priorSearchText release]" to dealloc is also required
  ...
}

// in the .m
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
  [NSObject cancelPreviousPerformRequestsWithTarget:self
                                           selector:@selector(request:)
                                             object:priorSearchText];
  [priorSearchText release], priorSearchText = [searchText retain];
  if (YES /* ...or whatever validity test you want to apply */)
    [self performSelector:@selector(request:)
               withObject:searchText
               afterDelay:1.5];
}

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

0 голосов
/ 10 марта 2012

Переместить эту строку: [self performSelector:@selector(request:) withObject:searchText afterDelay:1.5]; из вашего textDidChange метода и положить его в текст начался метод редактирования: - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar

...