Como detectar uma pausa na input para UISearchBar / UITextField?

Eu tenho o seguinte código UISearchbar:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; NSString* endpoint =[NSString stringWithFormat:@"http://www.someurl/", [searchText stringByReplacingOccurrencesOfString:@" " withString:@"+"]]; NSURL* url = [NSURL URLWithString:endpoint]; NSURLRequest* request = [NSURLRequest requestWithURL:url]; GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request]; [myFetcher beginFetchWithDelegate:self didFinishSelector:@selector(searchResultsFetcher:finishedWithData:error:)]; } 

Eu quero enviar este pedido após uma pausa na input e redefinir o timer toda vez que um personagem é atingido. Como posso fazer isso?

Não precisa usar o NSTimer.

 - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(request) object:nil]; //..... [self performSelector:@selector(request) withObject:nil afterDelay:yourpausetime]; } 

No método textDidChange , crie um NSTimer, digamos, 2 segundos. Se o timer já existir, invalide e recrie o timer. (Código não testado 🙂

 - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { if (myTimer) { if ([myTimer isValid]) { [myTimer invalidate]; } [myTimer release], myTimer = nil; } myTimer = [[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(userPaused:) userInfo:nil repeats:NO] retain]; } 

Quando o usuário parar de digitar por 2 segundos, -userPaused: será chamado e seu timer será automaticamente invalidado (embora não seja nulo). Quando o usuário começar a digitar novamente, um novo timer será configurado.

Eu consegui adaptar a resposta de Sven Tan ao meu código existente no Swift. No meu caso, estou enviando a string para um método que carrega os resultados da pesquisa como asynchronous. Além disso, não estou usando o UISearchBar, mas sim um antigo UITextField simples.

 var currentTempQuery = "" ... func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if let t = textField.text { let s: NSString = t let newString = s.stringByReplacingCharactersInRange(range, withString: string).trim() NSObject.cancelPreviousPerformRequestsWithTarget(self, selector:#selector(MyViewController.sendSearchRequest(_:)), object: currentTermQuery) // Don't replace currentTermQuery until after the cancelPreviousPerformRequestWithTarget call currentTermQuery = newString performSelector(#selector(MyViewController.sendSearchRequest(_:)), withObject: newString, afterDelay: 1) } return true } 

Aqui está o seletor que está sendo chamado:

 func sendSearchRequest(text: String?) { // Call async search method here... } 

A maneira como o cancelPreviousPerformRequestsWithTarget funciona é que você precisa passar o mesmo destino, seletor e object que foi passado na chamada performSelector para que a solicitação anterior seja cancelada. Na minha implementação, como estou passando apenas uma string, preciso preservar a string de solicitação atual entre as chamadas para que eu possa referenciá-la para cancelar solicitações.

O resultado funciona para digitar e excluir caracteres no meu UITextField. Apenas uma pesquisa é enviada por alteração de termo de pesquisa principal.

Como eu disse, semelhante ao que Sven Tan postou, mas com um uso ligeiramente diferente. Espero que isso ajude algumas pessoas.

Excelente código e funcionando perfeito para mim. Eu encontrei aqui Substituindo um NSTimer com performSelector: withObject: afterDelay . Graças a solução Ben … todas as recompensas para ele eu só copie aqui para ser encontrado fácil

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { //because the view can be unloaded we must store all data so that its state can be restored in viewDidLoad self.searchQuery = [textField.text stringByReplacingCharactersInRange:range withString:string]; SEL fetchSearchResults = @selector(fetchSearchResults); //cancel the previous search request [[self class] cancelPreviousPerformRequestsWithTarget:self selector:fetchSearchResults object:nil]; //perform the search in a seconds time. If the user enters addition data then this search will be cancelled by the previous line [self performSelector:fetchSearchResults withObject:nil afterDelay:1]; return YES; } - (void)fetchSearchResults { NSLog(@"performing search %@", self.searchQuery); ... } 

Bloqueie a input de texto para sua pesquisa e faça com que um NSTimer chame um seletor. Mostre um indicador de algum tipo para que o usuário não pense que algo está errado. Quando o seletor triggers, o controle retorna ao usuário para continuar digitando

 [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(targetMethod:) userInfo:nil repeats:NO];