2011-08-15 14 views
15

Tengo el siguiente código UISearchbar:¿Cómo detectar una pausa en la entrada para UISearchBar/UITextField?

- (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:)]; 
} 

Quiero enviar esta solicitud después de una pausa en la entrada y restablezca el contador cada vez que un personaje es golpeado. ¿Cómo puedo hacer esto?

Respuesta

52

No tiene que usar NSTimer.

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

      //..... 

      [self performSelector:@selector(request) withObject:nil afterDelay:yourpausetime]; 

     } 
+2

Solución mucho más elegante que un NSTimer, creo.Podría causar problemas dependiendo del runloop y la entrada o solicitud del usuario, tal vez? Hmm, ya no más que un temporizador aunque – RSully

+0

¡Agradable! Aquí hay otro ejemplo con comentarios detallados: http://benedictcohen.co.uk/blog/archives/157 – ma11hew28

+0

no funciona, el selector llama repetidamente aunque estamos cancelando (swift 3) – Saif

-1

Bloquea la entrada de texto a tu búsqueda y haz que un NSTimer llame a un selector. Muestra un indicador de algún tipo para que el usuario no piense que algo anda mal. Cuando el selector se dispare devuelva el control al usuario para continuar escribiendo

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

Un montón de NSTimers se dispararán mientras el usuario escribe. ¿Cómo puedo restablecer el NSTimer cuando se escribe un caracter? –

+0

Lo tomo de vuelta. invalidar solo cuando desee detener la activación de un temporizador. La muestra anterior tiene repeticiones: NO, por lo que se disparará una vez y ya está. = –

+0

¿No estoy seguro de cómo bloquear el ingreso de texto hasta que termine el temporizador? ¿Podrías mostrarme un ejemplo? –

6

En el método textDidChange crear una NSTimer, dicen que vale 2 segundos. Si el temporizador ya existe, invalide y vuelva a crear el temporizador. (Código :) No comprobado

- (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]; 
} 

Cuando el usuario deja de escribir durante 2 segundos, -userPaused: se llama y el temporizador será nula de pleno (aunque no nula). Cuando el usuario comienza a escribir de nuevo, se configurará un nuevo temporizador.

+0

¡Funciona como un encanto! – Wirsing

0

Excelente código y trabajo perfecto para mí. Lo encontré aquí Replacing an NSTimer with performSelector:withObject:afterDelay. Gracias a solución Ben ... todas las bondades que le acabo de copiarlo aquí para encontrar 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); 
    ... 
} 
1

yo era capaz de adaptar la respuesta de Sven Tan a mi código existente en Swift. En mi caso, estoy enviando la cadena a un método que carga los resultados de búsqueda asincrónicos. Además, no estoy usando UISearchBar, sino más bien un viejo y simple UITextField.

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 
} 

Aquí es el selector que se está llamando:

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

La forma en que cancelPreviousPerformRequestsWithTarget funciona es que necesita para aprobar el mismo objetivo, el selector, y el objeto que fue aprobada en la llamada performSelector con el fin para que la solicitud anterior sea cancelada En mi implementación, dado que paso solo una cadena, necesito preservar la cadena de solicitud actual entre las llamadas para poder hacer referencia a ella para cancelar las solicitudes.

El resultado funciona para escribir y borrar caracteres en mi UITextField. Solo se envía una búsqueda por cambio de término principal de búsqueda.

Como dije, similar a lo que Sven Tan publicó pero con un uso ligeramente diferente. Espero que esto ayude a algunas personas.

Cuestiones relacionadas