Rozwiązanie Swift 4 oraz kilka ogólnych uwag:
Są to wszystkie rozsądne podejścia, ale jeśli chcesz wzorowego zachowania automatycznego wyszukiwania, naprawdę potrzebujesz dwóch oddzielnych liczników czasu lub komunikatów.
Idealnym zachowaniem jest to, że 1) automatyczne wyszukiwanie jest uruchamiane okresowo, ale 2) niezbyt często (ze względu na obciążenie serwera, przepustowość sieci komórkowej i możliwość powodowania zacinania się interfejsu użytkownika) oraz 3) uruchamia się szybko, gdy tylko nastąpi przerwa w wpisywanie przez użytkownika.
Możesz osiągnąć to zachowanie za pomocą jednego długoterminowego timera, który uruchamia się zaraz po rozpoczęciu edycji (sugeruję 2 sekundy) i może działać niezależnie od późniejszej aktywności, plus jeden krótkoterminowy zegar (~ 0,75 sekundy), który jest resetowany co zmiana. Wygaśnięcie któregokolwiek z liczników uruchamia automatyczne wyszukiwanie i resetuje oba liczniki.
Efektem netto jest to, że ciągłe wpisywanie powoduje automatyczne przeszukiwanie co długie sekundy, ale pauza gwarantuje uruchomienie automatycznego wyszukiwania w ciągu krótkich sekund.
Możesz zaimplementować to zachowanie w bardzo prosty sposób za pomocą poniższej klasy AutosearchTimer. Oto jak z niego korzystać:
lazy var timer = AutosearchTimer { [weak self] in self?.performSearch() }
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
timer.activate()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
performSearch()
}
func performSearch() {
timer.cancel()
}
AutosearchTimer obsługuje własne czyszczenie po zwolnieniu, więc nie musisz się o to martwić w swoim własnym kodzie. Ale nie podawaj timera silnego odniesienia do siebie, bo utworzysz cykl odniesienia.
Poniższa implementacja wykorzystuje liczniki czasu, ale jeśli wolisz, możesz ją przekształcić pod kątem operacji wysyłkowych.
class AutosearchTimer {
let shortInterval: TimeInterval
let longInterval: TimeInterval
let callback: () -> Void
var shortTimer: Timer?
var longTimer: Timer?
enum Const {
static let longAutosearchDelay: TimeInterval = 2.0
static let shortAutosearchDelay: TimeInterval = 0.75
}
init(short: TimeInterval = Const.shortAutosearchDelay,
long: TimeInterval = Const.longAutosearchDelay,
callback: @escaping () -> Void)
{
shortInterval = short
longInterval = long
self.callback = callback
}
func activate() {
shortTimer?.invalidate()
shortTimer = Timer.scheduledTimer(withTimeInterval: shortInterval, repeats: false)
{ [weak self] _ in self?.fire() }
if longTimer == nil {
longTimer = Timer.scheduledTimer(withTimeInterval: longInterval, repeats: false)
{ [weak self] _ in self?.fire() }
}
}
func cancel() {
shortTimer?.invalidate()
longTimer?.invalidate()
shortTimer = nil; longTimer = nil
}
private func fire() {
cancel()
callback()
}
}