Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] Debounce 직접 구현해보기 본문

iOS 응용 (swift)

[iOS - swift] Debounce 직접 구현해보기

jake-kim 2024. 2. 13. 01:31

기초 지식) Throttle와 Debounce 개념

  • throttle을 10초로 걸어놓은 경우, 이벤트가 3번 발생했을 때 첫번째 이벤트만 10초후에 실행
  • debounce를 10초로 걸어놓은 경우, 이벤트가 3번 발생했을 때 마지막 이벤트가 발생하고 나서 10초후에 실행 (이벤트가 도중에 들어오면 또 10초 연장된 후 발행)
  • 차이점?
    • throttle은 무조건 10초안에 이벤트가 하나씩 발행되고, debounce는 10초가 지나기 전에 또 다른 이벤트가 들어오면 다시 10초 딜레이 후 마지막 이벤트를 실행
  • 사용처
    • throttle: 버튼 탭
    • debounce: 검색 입력

Debounce 직접 구현해보기

  • Debouncer 클래스 선언
class Debouncer {
}
  • 일정 seconds 후에 실행되어야하므로 초기화값에 seconds값을 받도록 설정
class Debouncer {
    private let seconds: Int
    
    init(seconds: Int) {
        self.seconds = seconds
    }
}
  • 구현해야하는 기능
    • 1) 이벤트를 5초후에 실행을 예약
    • 2) 5초가 지나기 전에 또 다른 이벤트를 실행 요청이 온다면 이전 이벤트를 취소
  • 위 기능들은 DispatchWorkItem이나 OperationQueue를 사용하면 작업을 언제든지 cancel할 수 있고 delay로 구현이 가능
  • DispatchWorkItem을 사용한다면 이전 작업을 기록하고 있어야하므로 전역변수로 선언
class Debouncer {
    private var workItem: DispatchWorkItem? // <-
    private let seconds: Int
    
    init(seconds: Int) {
        self.seconds = seconds
    }
}
  • run이라는 메서드에서 이전 작업을 취소하고 새로운 작업을 실행시키는 코드 추가
func run(_ closure: @escaping () -> ()) {
    self.workItem?.cancel()
    let newWork = DispatchWorkItem(block: closure)
    workItem = newWork
    DispatchQueue.main.asyncAfter(deadline: .now() + Double(seconds), execute: newWork)
}

(완료)

  • 사용하는쪽에서 Debouncer 인스턴스를 만들고 debounce기능을 넣고싶은 곳에 감싸서 적용
class ViewController: UIViewController {
    private let button = {
        ...
    }()
    private let debouncer = Debouncer(seconds: 3)
    
    ...
    
    @objc private func tap() {
        debouncer.run {
            print("Tap!")
        }
    }
}

(버튼을 3초안에 여러번 탭하면 또다시 3초후에 실행됨)

* 전체 코드: https://github.com/JK0369/ExDebounce

Comments