이지벳Proxy,이지벳ProxyType
* 이글은 Swift 3.0 , RxSwift 3.0.0 을 기준으로 작성되었습니다.
Swift 에서 일반적인 이지벳 / protocol 를 사용하는 구조를 생각해보자.
컬러를 선택하는 커스텀 뷰를 만들었다고 가정하자.
이 뷰는 아래와 같이 선택된 컬러를 전달하는 protocol 을 이지벳 method 로 사용한다.
protocol ColorPicker {
func selected(color: UIColor)
}
class ColorPickerView: UIView {
weak var delegate: ColorPicker? = nil
func selected(color: UIColor){
self.이지벳?.selected(color: color)
}
}
class ViewController: UIViewController,ColorPicker{
var pickerView: ColorPickerView?
func selected(color: UIColor) {
print("selected color")
}
override func viewDidLoad() {
super.viewDidLoad()
pickerView = ColorPickerView()
pickerView?.delegate = self
}
}
만약 아래와 같은 구문으로 쓴다면 어떨까?
pickerView?.rx_selectedColor.subscribe(onNext: { color in
print("onNext")
}).addDisposableTo(disposeBag)
이렇게 이지벳 method 를 rx_이지벳 형태로 확장해보자.
Rx 의 이지벳Proxy 를 상속받고,DelegateProxyType,ColorPicker 프로토콜에 따르도록 아래와 같이 구성한다.
class RxColorPickerDelegateProxy: 이지벳Proxy,이지벳ProxyType,ColorPicker{
internal func selected(color: UIColor) {
}
static func current이지벳For(_ object: AnyObject) - AnyObject? {
let pickerView: ColorPickerView = object as! ColorPickerView
return pickerView.delegate as AnyObject?
}
static func setCurrent이지벳(_ 이지벳: AnyObject?, toObject object: AnyObject) {
let pickerView: ColorPickerView = object as! ColorPickerView
pickerView.delegate = delegate as? ColorPicker
}
}
extension ColorPickerView {
public var rx_delegate: DelegateProxy {
return RxColorPickerDelegateProxy.proxyForObject(self)
}
public var rx_selectedColor: Observable<UIColor?{
returnrx_delegate.sentMessage(#selector(RxColorPickerDelegateProxy.selected(color:))).map{ a in a[0] as? UIColor }
}
}
* 여기서 a 는 selected 함수parameter를 의미한다. Observable<[Any] 로 전달 되므로필요한 형태로 mapping 해주면 된다.
pickerView?.rx_selectedColor.subscribe(onNext: { color in
print("onNext")
}).addDisposableTo(disposeBag)
- 간단하게 2번 과정을 통해 바로 observable 을 생성하면 된다.
예를 들어 UIScrollView이지벳 의 scrollViewWillBeginDragging 를Observable 로 사용하려면
tableView.rx.이지벳
.sentMessage(#selector(UIScrollView이지벳.scrollViewWillBeginDragging(_:)))
.map{ a in a[0] as? UIScrollView }.subscribe(onNext: { scrollView in
}).addDisposableTo(disposeBag)
이렇게 해줘도 되고 위에서 확장한 것과 같이 UITableView 에서 확장해서 rx 메서드로 만들어 두고 써도 된다.
사견: RxSwift 를 프로젝트 전반적으로 사용한다면 이런 다양한 방법을 통해 코드를 일관성 있게 유지할 수 있을 것 같다. 또 이 렇게 이지벳 도 Rx 메서드로 만들어 둔다면 다른 Observable 과의 결합이나, Utility 함수들을 사용하면 더 활용도가 높을 것으로 생각한다.