Swift 4ソリューションといくつかの一般的なコメント:
これらはすべて合理的なアプローチですが、模範的な自動検索動作が必要な場合は、2つの別々のタイマーまたはディスパッチが実際に必要です。
理想的な動作は、1)自動検索が定期的にトリガーされるが、2)あまり頻繁ではない(サーバーの負荷、セルラー帯域幅、およびUIスタッターを引き起こす可能性があるため)、3)一時停止があるとすぐにトリガーされることです。ユーザーの入力。
この動作は、編集が開始されるとすぐにトリガーされ(2秒をお勧めします)、後のアクティビティに関係なく実行できる1つの長期タイマーと、毎回リセットされる1つの短期タイマー(〜0.75秒)で実現できます。変化する。いずれかのタイマーが期限切れになると、自動検索がトリガーされ、両方のタイマーがリセットされます。
正味の効果は、連続入力によって長周期秒ごとに自動検索が生成されることですが、一時停止すると短周期秒以内に自動検索がトリガーされることが保証されています。
この動作は、以下のAutosearchTimerクラスを使用して非常に簡単に実装できます。使用方法は次のとおりです。
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は解放されると独自のクリーンアップを処理するため、独自のコードでそれについて心配する必要はありません。ただし、タイマーに自己への強い参照を与えないでください。そうしないと、参照サイクルが作成されます。
以下の実装ではタイマーを使用していますが、必要に応じてディスパッチ操作の観点から再キャストできます。
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()
}
}