관리 메뉴

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

[iOS - swift] RxSwift의 Reactive로 Getter, Setter 만드는 방법 (Observable, ControlEvent, Binder) 본문

iOS 응용 (swift)

[iOS - swift] RxSwift의 Reactive로 Getter, Setter 만드는 방법 (Observable, ControlEvent, Binder)

jake-kim 2023. 7. 16. 01:14

RxSwift의 Reactive로 만든 getter, setter

  • myView라는 커스텀 뷰를 사용할 때, myView의 이벤트들을 rx 네임스페이스로 접근
    • getter부분: .rx.tapButton
    • setter부분: .rx.setTitleButton
func bind() {
    myView.rx.tapButton // <- getter
        .bind {
            print("tap!")
        }
        .disposed(by: disposeBag)
    
    button.rx.tap
        .map { "tap! other Button" }
        .bind(to: myView.rx.setTitleButton) // <- setter
        .disposed(by: disposeBag)
}
  • 위와같이 getter와 setter를 myView쪽에 구현하여, 이를 사용하는 쪽에서 매우 쉽게 접근이 가능
    • getter에서는 일반적인 binding처럼 접근
    • setter를 사용할땐 bind(to:)에 넣어서 간편하게 사용가능

ControlEvent, ControlProperty, Binder

  • getter와 setter를 구현하기에 앞서 ControlEvent, ControlProperty, Binder, Observable 차이를 알기
    • getter만 지원하는 것과 setter만 지원하는 것, 둘 다 지원하는 컴포넌트가 존재
  • getter 전용: controlEvent
  • setter 전용: binder

구현

  • RxSwift, RxCocoa 추가 (cocoapod 사용)
pod 'RxSwift'
pod 'RxCocoa'
  • MyView 구현
import UIKit
import RxSwift
import RxCocoa

final class MyView: UIView {
    fileprivate let button: UIButton = {
        let button = UIButton()
        button.setTitle("버튼", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    init() {
        super.init(frame: .zero)
        setupUI()
    }
    
    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    func setupUI() {
        addSubview(button)
        NSLayoutConstraint.activate([
            button.leadingAnchor.constraint(equalTo: leadingAnchor),
            button.trailingAnchor.constraint(equalTo: trailingAnchor),
            button.bottomAnchor.constraint(equalTo: bottomAnchor),
            button.topAnchor.constraint(equalTo: topAnchor),
        ])
    }
}
  • Reactive 확장
extension Reactive where Base: MyView {
    // TODO
}
  • 여기다 getter만 적용하는 프로퍼티를 구현하려면 Observable을 사용하여 구현
    • (getter만 지원하는 또다른 컴포넌트인 ControlEvent를 사용해도 무방)
var tapButton: Observable<Void> {
    base.button.rx.tap.asObservable()
}
  • setter만 적용하는 Binder를 사용하여 setter 구현
var setTitleButton: Binder<String> {
    Binder(base) { base, titleText in
        base.button.setTitle(titleText, for: .normal)
    }
}

(setter, getter 구현 완료)

  • 사용하는쪽에서는 rx 네임스페이스로 접근이 가능
// ViewController.swift

func bind() {
    myView.rx.tapButton
        .bind {
            print("tap!")
        }
        .disposed(by: disposeBag)
    
    button.rx.tap
        .map { "tap! other Button" }
        .bind(to: myView.rx.setTitleButton)
        .disposed(by: disposeBag)
}

 

* 전체 코드: https://github.com/JK0369/ExGetterSetterWithReactive

* 참고

https://ios-development.tistory.com/1169

Comments