일련의 값을 버퍼링하고, 버퍼링 된 값들 중에서 가장 최근 값만을 내보내는 연산자
(Operator) 중 하나입니다.
(주로 사용자 입력 또는 다른 이벤트를 처리할 때 유용하게 사용)
예를 들어 사용자가 텍스트 입력을 할 때 텍스트 필드에서 발생하는 변경 이벤트를 debounce를 사용하면 사용자의 입력이 일정 시간 동안 안정화될 때까지 이벤트를 처리하지 않고, 안정화된 입력 이벤트만을 처리할 수 있습니다.
delay
는 모든 이벤트에 동일한 지연을 적용하고, debounce
는 안정화된 입력만을 내보낸다는 차이가 있습니다.
import UIKit
import Combine
class DebounceViewController: UIViewController {
@IBOutlet weak var myLabel: UILabel!
static let identifier: String = "DebounceViewController"
var subscriptions = Set<AnyCancellable>()
private lazy var searchController: UISearchController = {
let searchController = UISearchController()
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.tintColor = .label
searchController.searchBar.searchTextField.accessibilityIdentifier = "mySearchBarTextField"
return searchController
}()
override func viewDidLoad() {
super.viewDidLoad()
configure()
bind()
}
}
private extension DebounceViewController {
func configure() {
navigationItem.title = "디바운스"
setupSearchController()
}
func setupSearchController() {
navigationItem.searchController = searchController
searchController.isActive = true
}
func bind() {
searchController.searchBar.searchTextField
.myDebounceSearchPublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] receivedValue in
guard let self = self else { return }
print("receivedValue: \(receivedValue)")
myLabel.text = receivedValue
}
.store(in: &subscriptions)
}
}
extension UISearchTextField {
var myDebounceSearchPublisher: AnyPublisher<String, Never> {
NotificationCenter.default.publisher(for: UISearchTextField.textDidChangeNotification, object: self)
.compactMap { $0.object as? UISearchTextField }
.map { $0.text ?? "" }
// delay는 값을 방출하는 시점을 지연시키는 역할, 주로 작업을 일정 시간 동안 지연시키고 타이밍을 조정할 때 사용
// .delay(for: 2, scheduler: RunLoop.main)
// debounce는 일정 시간 동안 발생하는 중간 값을 제거하여 마지막 값을 방출, 주로 사용자 입력과 같은 빠른 연속적인 이벤트에서 유용하게 사용
.debounce(for: 1, scheduler: RunLoop.main)
// 글자가 있을때만 이벤트 전달
.filter { $0.count > 0 }
.eraseToAnyPublisher()
}
}