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

发布于 2024-11-29 13:41:19 字数 739 浏览 3 评论 0原文

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

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

I have the following UISearchbar code:

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

I want to send this request after a pause in input and reset the timer everytime a character is hit. How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

假装爱人 2024-12-06 13:41:19

它不必使用 NSTimer。

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

          //.....

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

        }

It doesn't have to use NSTimer.

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

          //.....

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

        }
烧了回忆取暖 2024-12-06 13:41:19

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: 将被调用,并且您的计时器将自动失效(尽管不是零)。当用户再次开始打字时,将设置一个新的计时器。

In the textDidChange method create an NSTimer, say 2 seconds worth. If the timer already exists, invalidate and recreate the 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];
}

When the user stops typing for 2 seconds, -userPaused: will be called and your timer will be automatically invalidated (although not nil). When the user starts typing again a new timer will be setup.

初心未许 2024-12-06 13:41:19

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

I was able to adapt Sven Tan's answer to my existing code in Swift. In my case, I am sending the string to a method that loads the search results async. Additionally, I am not using the UISearchBar but rather a plain old 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
}

Here is the selector that is being called:

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

The way that cancelPreviousPerformRequestsWithTarget works is you need to pass the same target, selector, and object that was passed in the performSelector call in order for the previous request to be cancelled. In my implementation, since I am passing just a string, I need to preserve the current request string between calls so I can reference it to cancel requests.

The result works for typing and deleting characters into my UITextField. Only one search is sent per major search term change.

Like I said, similar to what Sven Tan posted but slightly different usage. Hopefully this helps some people out.

翻了热茶 2024-12-06 13:41:19

优秀的代码并且非常适合我。我在这里找到了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);
    ...
}

Excellent code and working perfect for me. I found it here Replacing an NSTimer with performSelector:withObject:afterDelay. Thanks to Ben solution ... all bounties to him i just copy it here to be found easy

- (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);
    ...
}
廻憶裏菂餘溫 2024-12-06 13:41:19

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

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

Block text input to your search and have an NSTimer call a selector. Show an indicator of some sort so the user doesn't think something is going wrong. 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];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文