【问题标题】:How to detect a pause in input for UISearchBar/UITextField?如何检测 UISearchBar/UITextField 的输入暂停?
【发布时间】:2011-10-27 01:03:51
【问题描述】:

我有以下 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:)];
}

我想在输入暂停后发送此请求,并在每次命中字符时重置计时器。我该怎么做?

【问题讨论】:

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


    【解决方案1】:

    它不必使用 NSTimer。

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

    【讨论】:

    • 我认为比 NSTimer 更优雅的解决方案。可能会根据运行循环和用户输入或请求导致问题,也许?嗯,不过是计时器而已
    • 不错!这是另一个带有详细 cmets 的示例:benedictcohen.co.uk/blog/archives/157
    • 不工作,选择器反复调用,即使我们正在取消(swift 3)
    【解决方案2】:

    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)。当用户再次开始输入时,将设置一个新的计时器。

    【讨论】:

      【解决方案3】:

      我能够将 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 发布的内容,但用法略有不同。希望这可以帮助一些人。

      【讨论】:

        【解决方案4】:

        优秀的代码和完美的工作对我来说。我在这里找到它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);
            ...
        }
        

        【讨论】:

          【解决方案5】:

          阻止文本输入到您的搜索并让 NSTimer 调用选择器。显示某种指示器,这样用户就不会认为出了什么问题。 When the selector fires give control back to the user to continue typing

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

          【讨论】:

          • 当用户输入时,一堆 NSTimer 会消失。输入字符时如何重置 NSTimer?
          • 我收回了。仅当您想停止计时器触发时才无效。上面的示例有重复:NO,所以它会触发一次并完成。 =
          • 我不确定如何在计时器完成之前阻止文本输入?你能给我举个例子吗?
          • 禁用字段或在 textDidChange 中添加条件或...取决于您想要的用户体验。想象一下,如果我刚刚好并且我想打字非常快?也许您应该在我停止输入特定时间后启动服务器调用。
          猜你喜欢
          • 1970-01-01
          • 2012-03-27
          • 1970-01-01
          • 2015-09-22
          • 1970-01-01
          • 2015-06-28
          • 2011-01-26
          • 1970-01-01
          • 2011-04-13
          相关资源
          最近更新 更多