develop
Throttle, Debounce 본문
함수를 일정 시간 이후에 실행할 수 있게 해준다.
예를 들어 UITextField에서 텍스트를 입력할 때마다 입력된 텍스트를 받게 되면 큰 비용이 일어나게 된다.
이 문제를 해결하려면
텍스트를 입력한 다음 일정 시간 동안 다음 텍스트를 입력 받지 못하면 이벤트가 일어나고
일정 시간 안에 텍스트를 입력 받으면 다시 다음 일정 시간을 기다리게 한다.
이 방법으로 큰 비용이 발생되지 않는다.
Debounce
입력이 될 때마다 일정 시간을 다시 기다린다.
위의 라인이 이벤트 발생이고 아래 라인이 이벤트가 호출되는 시점이다.
위의 1번 이벤트를 발생시키고 일정 시간 동안 이벤트 발생이 없어서 1번이 호출되었다.
위의 2번 이벤트를 발생시키고 일정 시간이 지나기 전에 3번, 4, 5, 6, 7번 이벤트를 발생 시켰고
7번 이벤트를 발생시키고 일정 시간 동안 이벤트 발생이 없어서 7번이 호출되었다.
8번 이벤트를 발생시키고 후 일정 시간 동안 이벤트 발생이 없어서 8번이 호출되었다.
class DebounceTextField: UITextField {
deinit {
self.removeTarget(self, action: #selector(self.editingChanged(_:)), for: .editingChanged)
}
private var workItem: DispatchWorkItem?
private var delay: Double = 0
private var callback: ((String?) -> Void)? = nil
func debounce(delay: Double, callback: @escaping ((String?) -> Void)) {
self.delay = delay
self.callback = callback
DispatchQueue.main.async {
self.callback?(self.text)
}
self.addTarget(self, action: #selector(self.editingChanged(_:)), for: .editingChanged)
}
@objc private func editingChanged(_ sender: UITextField) {
self.workItem?.cancel()
let workItem = DispatchWorkItem(block: { [weak self] in
self?.callback?(sender.text)
})
self.workItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + self.delay, execute: workItem)
}
}
let textField = DebounceTextField()
textField.debounce(delay: 0.3) { (text) in
print(text)
}
이제 텍스트 입력 후 0.3초 후에 텍스트를 받게 된다.
0.3초가 지나기 전에 텍스트를 입력하게 되면 이벤트가 callback되지 않고 다시 0.3초를 기다리게 된다.
Throttle
지정한 시간 간격으로 마지막 이벤트가 호출된다.
위의 라인이 이벤트 발생이고 아래 라인이 이벤트가 호출되는 시점이다.
위의 1번 이벤트를 발생시키고 일정 시간이 지나 마지막 이벤트인 1번이 호출되었다.
위의 2번 이벤트를 발생시키고 일정 시간이 지나 마지막 이벤트인 4번이 호출되었다.
위의 5번 이벤트를 발생시키고 일정 시간이 지나 마지막 이벤트인 7번이 호출되었다.
위의 8번 이벤트를 발생시키고 일정 시간이 지나 마지막 이벤트인 8번이 호출되었다.
class ThrottleTextField: UITextField {
deinit {
self.removeTarget(self, action: #selector(self.editingChanged(_:)), for: .editingChanged)
}
private var workItem: DispatchWorkItem?
private var delay: Double = 0
private var callback: ((String?) -> Void)? = nil
func throttle(delay: Double, callback: @escaping ((String?) -> Void)) {
self.delay = delay
self.callback = callback
DispatchQueue.main.async {
self.callback?(self.text)
}
self.addTarget(self, action: #selector(self.editingChanged(_:)), for: .editingChanged)
}
@objc private func editingChanged(_ sender: UITextField) {
if self.workItem == nil {
let text = sender.text
self.callback?(text)
let workItem = DispatchWorkItem(block: { [weak self] in
self?.workItem?.cancel()
self?.workItem = nil
if text != sender.text {
self?.callback?(sender.text)
}
})
self.workItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + self.delay, execute: workItem)
}
}
}
let textField = ThrottleTextField()
textField.throttle(delay: 0.3) { (text) in
print(text)
}
이제 0.3초 동안 일어난 이벤트 중 마지막 이벤트가 호출되고 다시 0.3초를 기다리게 된다.
텍스트 입력 시 바로 이벤트가 호출되고 특정 시간 동안 이벤트가 발생하지 않으면 호출되지 않고 이벤트가 발생하면 마지막 이벤트만 호출된다.
'iOS' 카테고리의 다른 글
Cache 앱의 캐시 사용하기 (0) | 2021.01.23 |
---|---|
Generic (0) | 2021.01.21 |
Declaration Attributes (0) | 2021.01.19 |
DispatchGroup (0) | 2021.01.18 |
final Keyword (0) | 2021.01.17 |