RxSwift를 사용해서 View의 subcomponent중 하나인
SearchBar를 만들어보겠습니다.
가장 먼저,
SearchBar만을 위한 SearchBar.Swift 파일을 생성해줍니다.
SearchBar.Swift 파일내에서
SearchBar 클래스를 생성합니다.
import UIKit
import RxSwift
import RXCocoa
class SearchBar: UISearchBar {
}
이때 UISearchBar는 UIKit framework에 속하는 것이기 때문에
import UIKit을 꼭 해주어야합니다.
또한 Rx로 작성할 것이므로 RxSwift와 RxCocoa도 import 해줍니다.
class SearchBar: UISearchBar {
let disposeBag = DisposeBag()
let searchButton = UIButton()
}
class SearchBar: UISearchBar {
let disposeBag = DisposeBag()
let searchButton = UIButton()
let searhButtonTapped = PublishRelay<Void>()
var shouldLoadResult = Observable<String>.of("")
}
세 가지 메소드 bind(), attribute(), layout()을 만들어
// -> Reative - Bind
private func bind() {
}
// -> UI - View attribution
private func attribute() {
}
// -> UI - SubviewLayout
private func layout() {
}
각각의 메소드에 필요한 코드를 나눠 작성해 줍니다.
override init(frame: CGRect) {
super.init(frame: frame)
bind()
attribute()
layout()
}
bind 메소드에서 searchBar 이벤트를 작성해줍니다.
먼저 위에서 생성해준 searchButtonTapped는
발생합니다.
따라서 , 위 두 이벤트를 merge 연산자를 사용하여 합쳐줍니다.
Observable
.merge(
searchButton.rx.tap.asObservable()
self.rx.searchButtonClicked.asObservable()
)
Observable
.merge(
searchButton.rx.tap.asObservable()
self.rx.searchButtonClicked.asObservable()
)
.bind(to: searchButtonTapped)
.disposed(by: disposebag)
SearchButtonTapped가 발생하면
키보드가 내려가는 이벤트가 발생해야합니다.
따라서
SearchButtonTapped
.asSignal()
.emit(to: self.rx.endEditing)
.disposed(by: disposeBag)
extension Reactive where Base: Searchbar {
var endEditing: Binder<Void> {
return Binder(base) { base, _ in
base.endEditing(true)
}
}
}
SearchButtonTapped가 실행되면, 상위 뷰에 SearchBar Text를 전달하는 ShouldLoadResult가 실행되어야합니다.
SearchButtonTapped가 ShouldLoadResult의 trigger입니다.
self.shouldLoadResult = SearchButtonTapped
.withLatestFrom(self.rx.text) { $1 ?? "" }
.filter { !$0.isEmpty }
.distinctUntilChanged()
searchBar의 UI 를 설정해줍니다.
여기서는 SearchButton 밖에 설정해 줄 것이 없기 때문에
private func attribute() {
searchButton.setTitle("검색", for: .normal)
searchButton.setTitleColor(.systemBlue, for: .normal)
}
위와 같이 설정해줍니다.
snapKit을 사용해서 searchButton과 searchTextField 의 constraints를 설정해줍니다.
private func layout() {
self.addSubview(searchButton)
searchTextField.snp.makeConstraints {
$0.leading.equalToSuperview().inset(12)
$0.trailing.equalTo(searhButton.snp.leading).offSet(-12)
$0.centerY.equalToSuperview()
}
searchButton.snp.makeConstraints {
$0.centerY.equalToSuperview()
$0.trailing.equalToSuperview.inset(12)
}
}