如何在 UISearchDisplayDelegate 中执行操作之前设置延迟?
How do I set a delay before performing an action in UISearchDisplayDelegate?
我有一个搜索显示控制器,它命中了一个 API 端点。我当前的代码将在每个字符上向 API 端点发出请求。我想做的是仅当用户停止输入 500 毫秒时才发出请求。
代码如下:
在 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
但实际上这不起作用,因为每次用户输入一个字符时,搜索都会延迟,但它仍在为用户输入的每个字符发出请求。
我不想过于复杂,但我觉得它应该超级简单而且我遗漏了一些东西。
调用 performSelector:withObject:afterDelay: 怎么样?它对所有 NSObjects 都可用,所以你可以从你的视图控制器中调用它。您可能需要担心的唯一一件事就是没有参加每一个活动并排队等待 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:
时,如果您的计时器实例为 null,请将其实例化并将其时间间隔设置为 500ms,并将其选择器设置为您在步骤 1 中创建的方法。如果计时器是不为空,使其无效并将其设置为一个新的计时器实例,具有与以前相同的 500 毫秒间隔和选择器。
4) 如果您丢失了搜索字符串,则创建一个 属性 来保存它并在每次调用 searchDisplayController:shouldReloadTableForSearchString:
时更新它。尽管我相信您应该可以使用 searchDisplayController.searchBar.text
.
之类的内容来访问它
您可以使用 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
});
我有一个搜索显示控制器,它命中了一个 API 端点。我当前的代码将在每个字符上向 API 端点发出请求。我想做的是仅当用户停止输入 500 毫秒时才发出请求。
代码如下:
在 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
但实际上这不起作用,因为每次用户输入一个字符时,搜索都会延迟,但它仍在为用户输入的每个字符发出请求。
我不想过于复杂,但我觉得它应该超级简单而且我遗漏了一些东西。
调用 performSelector:withObject:afterDelay: 怎么样?它对所有 NSObjects 都可用,所以你可以从你的视图控制器中调用它。您可能需要担心的唯一一件事就是没有参加每一个活动并排队等待 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:
时,如果您的计时器实例为 null,请将其实例化并将其时间间隔设置为 500ms,并将其选择器设置为您在步骤 1 中创建的方法。如果计时器是不为空,使其无效并将其设置为一个新的计时器实例,具有与以前相同的 500 毫秒间隔和选择器。
4) 如果您丢失了搜索字符串,则创建一个 属性 来保存它并在每次调用 searchDisplayController:shouldReloadTableForSearchString:
时更新它。尽管我相信您应该可以使用 searchDisplayController.searchBar.text
.
您可以使用 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
});