Ответ 1
Похоже, что предоставленное решение не работает, потому что аргумент "searchText" для cancelPreviousPerformRequestsWithTarget:selector:object:
не соответствует аргументу "searchText" предыдущему вызову performSelector:withObject:afterDelay:
; поэтому отложенные поисковые запросы помещаются в очередь с каждым изменением текста и никогда не отменяются.
Вы можете использовать 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:... для реального, поэтому я не знаю, скрывает ли он какие-либо сюрпризы. Если у вас возникли проблемы, добавьте NSLogs, ищите отложенные запросы, которые не будут отменены, когда они должны.