[Swift]RxSwift 없이 debounce, throttle 구현해보기

okstring·2022년 1월 12일
1
post-thumbnail

스터디에서 한 분이 debounce 관련된 질문을 받으셨다고 하셔서 궁금해 찾아보았고 참고하여 button에 적용시켜봤다.
생각보다 간단했는데 서브클래싱, 클로저 그리고 task를 캡슐화 할 수 있는DispatchWorkItem을 사용해서 구현하면 비슷하게 작동한다

Debounce

class DebounceButton: UIButton {
    
    deinit {
        self.removeTarget(self, action: #selector(self.editingChanged(_:)), for: .touchUpInside)
    }
    
    private var workItem: DispatchWorkItem?
    private var delay: Double = 0
    private var callback: ((Date) -> Void)? = nil
    
    func debounce(delay: Double, callback: @escaping ((Date) -> Void)) {
        self.delay = delay
        self.callback = callback
        self.addTarget(self, action: #selector(self.editingChanged(_:)), for: .touchUpInside)
    }
    
    @objc private func editingChanged(_ sender: UIButton) {
        self.workItem?.cancel()
        let workItem = DispatchWorkItem(block: { [weak self] in
            self?.callback?(Date())
        })
        self.workItem = workItem
        DispatchQueue.main.asyncAfter(deadline: .now() + self.delay, execute: workItem)
    }
}

Throttle

class ThrottleButton: UIButton {
    deinit {
        self.removeTarget(self, action: #selector(self.editingChanged(_:)), for: .touchUpInside)
    }

    private var workItem: DispatchWorkItem?
    private var delay: Double = 0
    private var callback: ((Date) -> Void)? = nil

    func throttle(delay: Double, callback: @escaping ((Date) -> Void)) {
        self.delay = delay
        self.callback = callback
        self.addTarget(self, action: #selector(self.editingChanged(_:)), for: .touchUpInside)
    }

    @objc private func editingChanged(_ sender: UIButton) {
        if self.workItem == nil {
            self.callback?(Date())
            let workItem = DispatchWorkItem(block: { [weak self] in
                self?.workItem?.cancel()
                self?.workItem = nil
            })
            self.workItem = workItem
            DispatchQueue.main.asyncAfter(deadline: .now() + self.delay, execute: workItem)
        }
    }
}

reference

https://docfriends.github.io/DevStrory/2019-01-29/swift-delay/

profile
step by step

0개의 댓글