【问题标题】:UISearchBar detect when user stop type and don't search immediately so detect pauseUISearchBar 检测用户何时停止输入并且不立即搜索所以检测暂停
【发布时间】:2012-03-27 10:01:34
【问题描述】:

我正在搜索实现一个从 url 检索信息的 UISearchbar,并使用默认方法:

 - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{

我可以立即检测到文本何时更改并执行 url 的获取,但是这样,文本类型很慢,因为 iPhone 正在搜索 url,所以我想在用户停止时开始获取 url写了几秒钟,所以我想检测输入的暂停以刷新表格视图,通过 url 检索信息。我找到了这个请求的旧帖子,我尝试了一个对我不起作用的解决方案:

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

    //.....

    [self performSelector:@selector(request:) withObject:searchText afterDelay:1.5];
}

-(void)request:(NSString *)myString
{
    NSLog(@"%@",myString);
}

以这种方式,当我输入请求方法时不会调用,但是当我停止输入时,它会为我输入的每个字符调用,所以默认方法相同,我错了吗?还是实现不正确?

【问题讨论】:

    标签: iphone ios uitableview text uisearchbar


    【解决方案1】:

    看起来提供的解决方案不起作用,因为cancelPreviousPerformRequestsWithTarget:selector:object: 的“searchText”参数与上一次调用performSelector:withObject:afterDelay: 的“searchText”参数不匹配;所以延迟搜索会在每次文本更改时排队,并且永远不会取消。

    您可以使用NSTimer 来延迟搜索的调用,并在文本更改时取消计时器:为您的对象提供NSTimer 属性或字段;在searchBar:textDidChange: 中取消任何现有计时器,然后创建并安排一个新计时器。计时器的目标应该调用您的搜索方法。

    类似的东西(在我的脑海中):

    // in your class' .h object fields
    {
      ...
      NSTimer *searchDelayer; // this will be a weak ref, but adding "[searchDelayer invalidate], searchDelayer=nil;" to dealloc wouldn't hurt
      ...
    }
    
    // in the .m
    
    -(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
    {
      [searchDelayer invalidate], searchDelayer=nil;
      if (YES /* ...or whatever validity test you want to apply */)
        searchDelayer = [NSTimer scheduledTimerWithTimeInterval:1.5
                                                         target:self
                                                       selector:@selector(doDelayedSearch:)
                                                       userInfo:searchText
                                                        repeats:NO];
    }
    
    -(void)doDelayedSearch:(NSTimer *)t
    {
      assert(t == searchDelayer);
      [self request:searchDelayer.userInfo];
      searchDelayer = nil; // important because the timer is about to release and dealloc itself
    }
    

    有些程序员对弱引用可能不像我在这里那么随意。

    [编辑添加:]

    如果您设置为使用 cancelPreviousPerformRequestsWithTarget...,您可以这样做:

    // in your class' .h object fields
    {
      ...
      NSString *priorSearchText; // this will NOT be a weak ref, so adding "[priorSearchText release]" to dealloc is also required
      ...
    }
    
    // in the .m
    -(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
    {
      [NSObject cancelPreviousPerformRequestsWithTarget:self
                                               selector:@selector(request:)
                                                 object:priorSearchText];
      [priorSearchText release], priorSearchText = [searchText retain];
      if (YES /* ...or whatever validity test you want to apply */)
        [self performSelector:@selector(request:)
                   withObject:searchText
                   afterDelay:1.5];
    }
    

    我认为我从未真正使用过 cancelPreviousPerformRequestsWithTarget:...,所以我不知道它是否隐藏了任何惊喜。如果您遇到问题,请添加 NSLog,查找延迟搜索未在应取消时取消。

    【讨论】:

    • 如何使用 NSString 实现第一个选项?你能写一个代码示例吗?
    • 好的,我会写点东西的。但不能保证不会出错,因为我没有在实际代码中尝试过这种方法。
    • 这条线在做什么? [自我请求:searchDelayer.userInfo]; ?
    • 我已经开始使用 swift 进行编码,那么如何使用 swift 来完成呢?
    【解决方案2】:

    移动这一行: [self performSelector:@selector(request:) withObject:searchText afterDelay:1.5]; 从您的textDidChange 方法中取出并将其放入文本中确实开始编辑方法: - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar

    【讨论】:

    • 但如果我在此方法中添加该行:- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar 这里没有 searchText 参数,我该怎么做...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 2011-04-13
    相关资源
    最近更新 更多