如何在UISearchDisplayDelegate中执行操作之前设置延迟?

时间:2015-03-30 18:58:11

标签: ios objective-c afnetworking uisearchbar nsoperationqueue

我有一个搜索显示控制器,可以访问API端点。我当前的代码将在每个char上向API端点发出请求。我想要做的只是当用户停止输入500ms时才发出请求。

以下是代码:

在UISearchDisplayDelegate

注意:searchQueue是一个NSOperationQueue对象。

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    [self.searchQueue cancelAllOperations];

    [self.searchQueue addOperationWithBlock:^(){
        [self.AFRequestManager.operationQueue cancelAllOperations];

        NSString *access_token = [[FBSDKAccessToken currentAccessToken] tokenString];

        NSDictionary *params = @{@"name": searchString, @"access_token": access_token };

        NSString *getUrl = [baseUrl stringByAppendingString:@"api/users/search"];
        [self.AFRequestManager GET:getUrl parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
            self.searchedUsers = responseObject;
            [self.searchDisplayController.searchResultsTableView reloadData];

        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Error: %@", error);
        }];
    }];

    return NO;
}

为用户输入的每个字符调用此委托方法,我想等到用户完成指定名称。

我尝试过使用NSTimer,但它很混乱。我绝对可以将searchString传递给userInfo。但是,一旦我使NSTimer无效,它就不能再次使用了。

我尝试使用dispatch_after,但实际上这不起作用,因为每次用户输入一个字符时,搜索都会延迟,但它仍然会请求用户输入的每个字符。

我不想过度复杂,但我觉得它应该非常容易,而且我错过了一些东西。

2 个答案:

答案 0 :(得分:1)

如何调用performSelector:withObject:afterDelay:?它可供所有NSObject使用,因此您可以从视图控制器中调用它。您唯一可能需要担心的是,不是每次事件都会发生,并排队等待2分钟的延迟:

- (void)performSelector:(SEL)aSelector
             withObject:(id)anArgument
             afterDelay:(NSTimeInterval)delay

示例(注意:为了演示,我编写了变量名称):

[self performSelector:@selector(callServer:) withObject:params afterDelay:0.5f];

<强>更新

似乎我的答案的第一部分是不够的。以下是一些可帮助您获得解决方案的新步骤:

1)创建一个NSTimer属性,以便您可以在任何需要的地方访问

2)将searchDisplayController:shouldReloadTableForSearchString:中的当前逻辑移动到新方法中,以便计时器可以将其用作选择器。例如:

- (void)callServerWithDictionary:(NSDictionary*)params;

3)每当调用searchDisplayController:shouldReloadTableForSearchString:时,如果您的计时器实例为空,则将其实例化并将其时间间隔设置为500毫秒,并将其选择器设置为您在步骤1中创建的方法。如果计时器不为空,使其无效并将其设置为等于具有与之前相同的500ms间隔和选择器的新计时器实例。

4)如果您丢失了搜索字符串,则创建一个属性来保存它,并在每次调用searchDisplayController:shouldReloadTableForSearchString:时更新它。虽然我相信您应该可以使用searchDisplayController.searchBar.text

之类的内容访问它

答案 1 :(得分:0)

您可以使用GCD dispatch_after。这是一些例子。

double delayInSeconds = 3.0;

dispatch_time_t buyTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));

dispatch_after(buyTime, dispatch_get_main_queue(), ^(void)
{
   //code that will be executed after delay
}

你可以用这个

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index) {
   // block will be executed 10 times
   // number of launch passes to block
});