Как обнаружить паузу во вводе для UISearchBar / UITextField? - PullRequest
15 голосов
/ 15 августа 2011

У меня есть следующий код 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:)];
}

Я хочу отправить этот запрос после паузы при вводе и сбрасывать таймер при каждом нажатии символа.Как я могу это сделать?

Ответы [ 5 ]

52 голосов
/ 15 августа 2011

Не нужно использовать NSTimer.

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

          //.....

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

        }
6 голосов
/ 15 августа 2011

В методе textDidChange создайте NSTimer, скажем, за 2 секунды.Если таймер уже существует, аннулируйте его и создайте заново.(Непроверенный код:)

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

Когда пользователь перестает печатать в течение 2 секунд, будет вызван параметр -userPaused: и ваш таймер будет автоматически отключен (хотя и не равен нулю).Когда пользователь начнет печатать снова, будет установлен новый таймер.

1 голос
/ 06 июня 2016

Мне удалось адаптировать ответ Свена Тана к моему существующему коду в Swift. В моем случае я отправляю строку в метод, который загружает результаты поиска асинхронно. Кроме того, я не использую UISearchBar, а просто старый 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
}

Вот вызываемый селектор:

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

Способ работы cancelPreviousPerformRequestsWithTarget заключается в том, что вам нужно передать ту же цель, селектор и объект, которые были переданы в вызове performSelector, чтобы предыдущий запрос был отменен. В моей реализации, поскольку я передаю только строку, мне нужно сохранять текущую строку запроса между вызовами, чтобы я мог ссылаться на нее для отмены запросов.

Результат работает для ввода и удаления символов в моем UITextField. На одно изменение основного поискового запроса отправляется только один запрос.

Как я уже сказал, похоже на то, что написал Свен Тан, но немного другое использование. Надеюсь, это поможет некоторым людям.

0 голосов
/ 02 июня 2016

Отличный код и идеально подходит для меня. Я нашел это здесь Замена NSTimer с executeSelector: withObject: afterDelay . Благодаря Бену решению ... ему всяческих даров Я просто скопирую его сюда, чтобы легко найти

- (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 голосов
/ 15 августа 2011

Блокируйте ввод текста в вашем поиске и вызовите NSTimer селектором. Покажите какой-нибудь индикатор, чтобы пользователь не думал, что что-то идет не так. Когда селектор срабатывает, верните управление пользователю, чтобы продолжить ввод

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