관리 메뉴

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

[RxCocoa] 3. custom extensions 본문

RxSwift/RxCocoa

[RxCocoa] 3. custom extensions

jake-kim 2020. 8. 5. 19:29

custom extension이란?


객체.rx.함수접근이 가능하게끔 표현

 

첫 번째 방법, Binder


* Oberver only (Observable처럼 값을 받아서 처리한다는 개념이 아닌, 함수처럼 안에서 수행하라는 의미)

* Main Scheduler에서 수행하는 것이 default

class ViewController: UIViewController {

    let bag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        let obs = Observable.of(true)

        rx.myCustom.onNext(false) // observer라 가능

        rx.myCustom.subscribe // observer라 불가능

        obs.asDriverOnErrorNever()
            .drive(rx.myCustom)
            .disposed(by: bag)
    }
}

extension Reactive where Base: ViewController2 {

    var myCustom: Binder<Bool> {
        return Binder(self.base) { (vc, boolValue) in // (Base, 변수 타입)
            switch boolValue {
            case true:
                vc.view.backgroundColor = .black
            case false:
                vc.view.backgroundColor = .white
            }
        }
    }
}

접근객체.rx.정의한변수

값(Bool).Base객체.drive(rx.myCustom) Base객체 rx mycustom
쓰임 접근하려는 객체 rx 정의한 변수
의미 Base에서 정의한 타입 인터페이스 같은 개념 직접 정의한 내용 처리

두 번째 방법, ControlEvent


* Observable only

* 절대 error하지 않음 (deallocate될때만 Complete)

* MainScheduler에서 수행

class ViewController: UIViewController {

    let bag = DisposeBag()
    @IBOutlet weak var btn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        btn.rx.myCustomTap
            .subscribe(onNext: { // Observable이라 가능
                print($0)
            }).disposed(by: bag)

        btn.rx.myCustomTap.onNext // Observable이라 불가능
    }
}

extension ObservableType {
    func asDriverOnErrorNever() -> Driver<Element> {
        return asDriver { (error) in
            return .never()
        }
    }
}

extension Reactive where Base: UIButton {
    var myCustomTap: ControlEvent<Void> {
        print("커스텀 하면 이렇게 중간에 기능 끼워넣을 수 있음")
        return self.controlEvent(.touchUpInside)
    }
}
값(Void).UIButton객체.rx.myCustomTap ControlEvent<Void> rx myCustomTap
쓰임 접근하려는 객체 rx 정의한 변수
의미 Base에서 정의한 타입 인터페이스 같은 개념 직접 정의한 내용 처리

* Binder와 차이: ControlEvent는 Observable이기 때문에 subscribe가능

 

cf) Observable은 계속 create하는 것이고, Observer는 create하지 않는 것

Observer - onNext해서 이벤트 추가

Observable  - subscribe접근하여 발생한 이벤트에 접근

세 번째 방법, ControlProperty


* Observer and Observable

* 절대 error하지 않음 / deallocated될때 Complete발생

* MainScheduler에서 진행

class ViewController: UIViewController {

    let bag = DisposeBag()
    @IBOutlet weak var btn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        btn.rx.myCustomTap.onNext("add") // Observer가능
        btn.rx.myCustomTap.subscribe(onNext: { value in // Observable가능
            print(value) // "커스텀.."
        }).disposed(by: bag)

    }
}

extension ObservableType {
    func asDriverOnErrorNever() -> Driver<Element> {
        return asDriver { (error) in
            return .never()
        }
    }
}

// 정의해줘야 하는 것 : func controlProperty(editingEvents:getter:setter:)
extension Reactive where Base: UIButton {
    var myCustomTap: ControlProperty<String> {
        return base.rx.controlProperty(editingEvents: .touchUpInside, getter: { base in
            return "커스텀.."
        }, setter: { base, catchValue in

            print("value1=\(base)") // value1=<UIButton: 0x7fc7da408260; frame = (184 389; 46 32); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6000011a95a0>>

            print("value2=\(catchValue)") // "value2=add"
        })
    }
}

 

 

Comments