관리 메뉴

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

[RxCocoa] 4. Delegate Proxy - Delegate를 rx로 바꾸어 사용하기 본문

RxSwift/RxCocoa

[RxCocoa] 4. Delegate Proxy - Delegate를 rx로 바꾸어 사용하기

jake-kim 2020. 8. 5. 23:20

Delegate Proxy란?

delegate를 사용하는 부분을 RxSwift로 표현할 수 있도록 하는 것

* 원리 : DelegateProxy.swift 파일과  DelegateProxyType.swift 이용

 

* Delegate개념 : 함수 실행위치를 미리 선언해 놓고, 구현은 직접 하라고 delegate시키는 것 -> (protocol로 선언)

import UIKit
import RxSwift
import RxCocoa

protocol MyDelegate {
    func willStart()
    func end()
}

class UISomething: NSObject {
    var delegate: MyDelegate? = nil

    func start() {
        delegate?.willStart() // 이 함수를 델리게이트 시킴
        print("여기에 어떤 작업 실행 (이미지 pick!)")
        delegate?.end() // 이 함수를 델리데이트 시킴
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let some = UISomething()
        some.delegate = self
        some.start()
    }
}

extension ViewController: MyDelegate {
    func willStart() {
        print("시작 전")
    }

    func end() {
        print("시작 후")
    }
}

* Rx에서 버튼을 탭한 경우의 delegate가 구현된 모습 예시

extension Reactive where Base: UIButton {
    
    /// Reactive wrapper for `TouchUpInside` control event.
    public var tap: ControlEvent<Void> {
        return controlEvent(.touchUpInside)
    }
}

Depegate Proxy구현하기

(구현하려는 파일의 네이밍 예시: UITextField+Rx)

 

1) 클래스 생성, 아래 클래스, 프로토콜들을 상속

- DelegateProxy<사용될 클래스

- 사용될 클래스의 델리게이트 프로토콜>

- DelegateProxyType, 델리게이트이름

//
//  MyButton+Rx.swift
//  DelegateTest
//
//  Created by 김종권 on 2020/09/27.
//  Copyright © 2020 jongkwon kim. All rights reserved.
//

import Foundation
import RxSwift
import RxCocoa
import UIKit

class RxUITextFieldDelegateProxy: DelegateProxy<UITextField, UITextFieldDelegate>, DelegateProxyType, UITextFieldDelegate{
    static func registerKnownImplementations() {
        <#code#>
    }

    static func currentDelegate(for object: UITextField) -> UITextFieldDelegate? {
        <#code#>
    }

    static func setCurrentDelegate(_ delegate: UITextFieldDelegate?, to object: UITextField) {
        <#code#>
    }
}

 

2) 세 가지 메소드 구현

//
//  MyButton+Rx.swift
//  DelegateTest
//
//  Created by 김종권 on 2020/09/27.
//  Copyright © 2020 jongkwon kim. All rights reserved.
//

import Foundation
import RxSwift
import RxCocoa
import UIKit

class RxUITextFieldDelegateProxy: DelegateProxy<UITextField, UITextFieldDelegate>, DelegateProxyType, UITextFieldDelegate{
    static func registerKnownImplementations() {
        self.register { (textField) -> RxUITextFieldDelegateProxy in
            RxUITextFieldDelegateProxy(parentObject: textField, delegateProxy: self)
        }
    }

    static func currentDelegate(for object: UITextField) -> UITextFieldDelegate? {
        return object.delegate
    }

    static func setCurrentDelegate(_ delegate: UITextFieldDelegate?, to object: UITextField) {
        object.delegate = delegate
    }
}

3) extension Reactive로 이벤트 등록

extension Reactive where Base: UITextField {
    var delegate : DelegateProxy<UITextField, UITextFieldDelegate> {
        return RxUITextFieldDelegateProxy.proxy(for: self.base)
    }

    var myTextFieldDelegate: Observable<Bool> {
        return
            delegate.methodInvoked(#selector(UITextFieldDelegate.textFieldShouldBeginEditing(_:)))
                .debug("델리게이트 성공")
                .map { _ in return true }
    }
}

사용

//
//  ViewController.swift
//  DelegateTest
//
//  Created by 김종권 on 2020/09/27.
//  Copyright © 2020 jongkwon kim. All rights reserved.
//

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let textField = UITextField()
        textField.rx.myTextFieldDelegate.asObservable()
            .bind(onNext: { _ in })
            .dispose()

    }
}

(결과)

'RxSwift > RxCocoa' 카테고리의 다른 글

[RxCocoa] 5. Traits (ControlProperty, ControlEvent, Driver)  (0) 2020.09.30
[RxCocoa] 3. custom extensions  (0) 2020.08.05
[RxCocoa] 2. 기본 개념  (0) 2020.07.06
[RxCocoa] 1. 맛보기  (0) 2020.06.28
Comments