Похоже, что предоставленное решение не работает, потому что аргумент "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, ищите отложенные поиски, которые не будут отменены, когда они должны.