Jak wykryć pauzę w wejściu dla UISearchBar/UITextField?

Mam następujący kod 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:)];
}

Chcę wysłać to żądanie po pauzie wejścia i zresetować timer za każdym razem, gdy postać zostanie trafiona. Jak mogę to zrobić?

Author: Sheehan Alam, 2011-08-15

5 answers

Nie musi używać NSTimer.

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

          //.....

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

        }
 52
Author: Sven Tan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-15 03:29:36

W metodzie textDidChange Utwórz NSTimer, powiedzmy o wartości 2 sekund. Jeśli timer już istnieje, Unieważnij i odtworz timer. (Untested code:)

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

Gdy użytkownik przestanie pisać na 2 sekundy, zostanie wywołane-userPaused:, a Twój timer zostanie automatycznie unieważniony (choć nie zerowy). Gdy użytkownik zacznie ponownie pisać, zostanie ustawiony nowy timer.

 6
Author: RSully,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-10 21:16:33

Udało mi się dostosować odpowiedź Svena Tana do mojego istniejącego kodu w Swift. W moim przypadku wysyłam łańcuch do metody, która ładuje wyniki wyszukiwania asynchronicznie. Dodatkowo, nie używam UISearchBar, ale raczej zwykły stary 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
}

Oto selektor, który jest wywoływany:

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

Sposób działania cancelPreviousPerformRequestsWithTarget polega na tym, że aby poprzednie żądanie zostało anulowane, musisz przekazać ten sam cel, Selektor i obiekt, który został przekazany w wywołaniu performSelector. W moim implementacja, ponieważ przekazuję tylko ciąg znaków, muszę zachować bieżący ciąg żądań między wywołaniami, aby móc odwoływać się do niego, aby anulować żądania.

Wynik działa przy wpisywaniu i usuwaniu znaków w moim polu UITextField. Tylko jedno wyszukiwanie jest wysyłane przy każdej ważnej zmianie terminu wyszukiwania.

Jak już mówiłem, podobne do tego, co napisał Sven Tan, ale nieco inne użycie. Mam nadzieję, że to pomoże niektórym ludziom.

 1
Author: i2097i,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-06 14:37:24

Doskonały kod i działa idealnie dla mnie. Znalazłem go tutaj zamieniając nstimer na performSelector: withObject: afterDelay. dzięki } ben rozwiązanie ... wszystkie bounties do niego po prostu skopiować go tutaj, aby znaleźć łatwe

- (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);
    ...
}
 0
Author: Nazir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-02 08:54:44

Zablokuj wprowadzanie tekstu do wyszukiwania i niech nstimer wywoła selektor. Pokaż jakiś wskaźnik, aby użytkownik nie myślał, że coś jest nie tak. Gdy selektor zostanie wywołany zwróć kontrolę użytkownikowi, aby kontynuował wpisywanie

[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(targetMethod:) userInfo:nil repeats:NO];
 -1
Author: David McGraw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-15 03:17:08