如何检测UISearchBar / UITextField的输入暂停?

时间:2011-08-15 03:10:48

标签: iphone objective-c cocoa-touch nstimer uisearchbar

我有以下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 个答案:

答案 0 :(得分:52)

它不必使用NSTimer。

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

          //.....

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

        }

答案 1 :(得分:6)

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:并且您的计时器将自动失效(尽管不是nil)。当用户再次开始键入时,将设置新的计时器。

答案 2 :(得分:1)

我能够让Sven Tan回答我在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中键入和删除字符。每个主要搜索字词更改仅发送一次搜索。

就像我说的那样,类似于Sven Tan发布但使用略有不同。希望这可以帮助一些人。

答案 3 :(得分:0)

优秀的代码和完美的工作对我来说。我在Replacing an NSTimer with performSelector:withObject:afterDelay找到了它。 感谢 Ben 解决方案......对他的所有赏金我只需将其复制到此处即可轻松找到

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

答案 4 :(得分:-1)

阻止搜索文本输入并让NSTimer调用选择器。显示某种指标,以便用户不会认为出现问题。当选择器触发时,将控制权交还给用户以继续键入

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