Swift 4 솔루션 및 몇 가지 일반적인 설명 :
이들은 모두 합리적인 접근 방식이지만 모범적 인 자동 검색 동작을 원한다면 실제로 두 개의 개별 타이머 또는 디스패치가 필요합니다.
이상적인 동작은 1) 자동 검색이 주기적으로 트리거되지만 2) 너무 자주 (서버로드, 셀룰러 대역폭 및 UI 끊김을 유발할 수있는 가능성으로 인해), 3) 일시 중지되는 즉시 빠르게 트리거되는 것입니다. 사용자의 입력.
이 동작은 편집이 시작되는 즉시 트리거되고 (2 초 권장) 이후 활동에 관계없이 실행이 허용되는 하나의 장기 타이머와 매번 재설정되는 하나의 단기 타이머 (~ 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()
}
}