Как обнаружить паузу во вводе для UISearchBar/UITextField?
У меня есть следующий код 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:)];
}
Я хочу отправить этот запрос после паузы во входе и reset таймера каждый раз, когда персонаж попадает. Как я могу это сделать?
Ответы
Ответ 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];
}
Ответ 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: и ваш таймер будет автоматически аннулирован (хотя и не равен нулю). Когда пользователь снова начнет вводить текст, будет настроен новый таймер.
Ответ 3
Я смог адаптировать Sven Tan к моему существующему коду в Swift. В моем случае я отправляю строку методу, который загружает результаты поиска async. Кроме того, я не использую 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. Только один поиск отправляется на каждое изменение поискового запроса.
Как я уже сказал, похоже на то, что написал Свен Тан, но немного другое использование. Надеюсь, это поможет некоторым людям.
Ответ 4
Отличный код и идеальная работа для меня. Я нашел его здесь Замена NSTimer на performSelector: withObject: afterDelay. Благодаря решению Бена... все щедрости ему Я просто скопирую его здесь, чтобы его легко найти
- (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 для селектора. Покажите какой-то индикатор, чтобы пользователь не думал, что что-то идет не так. Когда срабатывает селектор, пользователь возвращается к следующему типу
[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(targetMethod:) userInfo:nil repeats:NO];