Extension Reactive (RxSwift)
RxSwift는 커스터마이징을 확장하여 사용할 수 있음.
- RxSwift 내부 코드를 분석하다보면 Reactive.swift 파일에 custom포인트로 사용하라고 안내하고 있음
연관포스팅
- [iOS RxStarScream 총정리](https://rldd.tistory.com/271)
- [iOS Starscream 총정리](https://rldd.tistory.com/272)
- [iOS RxDelegateProxy 만들어보기 #1](https://rldd.tistory.com/273)
- [iOS RxDelegateProxy 만들어보기 #2 - StarScream + RxProxy](https://rldd.tistory.com/274)
- [Extension Reactive (RxSwift)](https://rldd.tistory.com/275)
목차
- Reactive.swift 파일 살펴보기
- RxSwift 내부에서 사용하는 Reactive.swift 어떻게 사용하는지 보기
- 몇가지 예제
- UIViewController + Rx
- UIButton + Rx
- UITextField + Rx
- Binder 내부 구현 살펴보기
Reactive.swift 파일 살펴보기
Use `Reactive` proxy as customization point for constrained protocol extensions.
General pattern would be:
// 1. Extend Reactive protocol with constrain on Base
// Read as: Reactive Extension where Base is a SomeType
extension Reactive where Base: SomeType {
// 2. Put any specific reactive extension for SomeType here
}
With this approach we can have more specialized methods and properties using
`Base` and not just specialized on common base type.
*/
public struct Reactive<Base> {
/// Base object to extend.
public let base: Base
/// Creates extensions with base object.
///
/// - parameter base: Base object.
public init(_ base: Base) {
self.base = base
}
}
RxSwift 내부에서 사용하는 Reactive.swift 어떻게 사용하는지 보기
아래처럼 확장해서 사용하고 있음
extension Reactive where Base: UIButton {
/// Reactive wrapper for `TouchUpInside` control event.
public var tap: ControlEvent<Void> {
return controlEvent(.touchUpInside)
}
}
들어가기 전 기본 용어 간단 정리
- ControlEvent - 값을 관찰할 수는 있으나, 값을 주입시키지는 못함.
- ControlProperty - 값을 주입시킬 수도 있고, 값의 변화도 관찰할 수 있다.
- Binder - 값을 주입시킬 수 있으나, 값의 변화는 관찰하지 못함.
UIViewController+Rx
RxSwift를 Extension으로 바꾸기
import UIKit
import RxCocoa
import RxSwift
extension Reactive where Base: UIViewController {
var viewWillAppear: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewWillAppear(_:))).map { _ in }
return ControlEvent(events: source)
}
}
Usage
rx.viewWillAppear // UIViewController+Rx에 정의
.asObservable() // 반환되는 이벤트를 옵저버블 타입으로 받는다. (공식문서 link에 의하면 From으로 연결되어 있음)
.bind(to: viewWillAppearSubject)
.disposed(by: disposeBag)
UIButton+Rx
import UIKit
import RxCocoa
import RxSwift
extension Reactive where Base: UIButton {
// 같은 기능을 재사용하기 위한 목적!
public var customChangeTitle: Binder<String> {
let s = Binder<String>(base) { btn, text in
btn.setTitle(text, for: [])
}
return s
} // 같은 기능을 재사용하기 위한 목적!
}
위 아래 두 코드는 target이 base임으로 같은 기능을 한다.
extension Reactive where Base: UIButton {
// 같은 기능을 재사용하기 위한 목적!
public var customChangeTitle: Binder<String> {
let s = Binder<String>(base) { _, text in
base.setTitle(text, for: [])
}
return s
}
}
Binder<String>(base, binding: {}) // 클로저 구문 이렇게도 작성 가능
Usage
함수가 사라져서 훨씬 더 깔끔해짐
myButton.rx
.tap
.map{ "text" }
.bind(to: myButton.rx.customChangeTitle)
.disposed(by: bag)
UITextField+Rx
ControlProperty는 값을 주입할 수 있기 때문에 아래처럼 사용할 수 있음
import UIKit
import RxCocoa
import RxSwift
extension Reactive where Base: UITextField {
public var text: ControlProperty<String?> {
value
}
}
textField.rx.text.onNext("Hello") // 값을 주입할 수 있기 때문에
textField.rx.text.subcribe(onNext: { _ in }) // 값을 관찰할 수 있기 때문에
Binder 원형에 대해서 살펴보기
extension으로 Binder를 사용하려고 하는 경우에는 target을 받아야 함.
'apple > RxSwift, ReactorKit' 카테고리의 다른 글
iOS RxAction (RxSwift Community) (0) | 2022.01.19 |
---|---|
RxSwift ch 18. Table & Collection views (0) | 2022.01.18 |
iOS RxDelegateProxy 만들어보기 #1 (0) | 2022.01.12 |
iOS RxStarScream 총정리 (0) | 2022.01.12 |
RxSwift 06 RxDataSources (0) | 2021.08.19 |