iOS RxDelegateProxy 만들어보기
Delegate를 RxSwift에 통합하여 사용하기 위해 Proxy를 만드는 방법을 학습
연관포스팅
- [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)
샘플코드
목차
- Protocol과 Delegate 개념 간단 정리
- RxDelegateProxy GuideLine
Protocol과 Delegate 개념 간단 정리
RxDelegateProxy를 만들어보기 위해서는 Delegate와 Protocol에 대해서 간단하게 정리
아래는 테이블 뷰 예시코드에서 VC2에 있는 Delegate를 VC1에 위임할 수 있음.
- 이렇게 할 경우 보다시피 VC2에서 Delegate의 구현체를 VC1에 위임하여 구현체를 구현하지 않아도 에러가 나지 않음.
class VC1: UIViewController, UITableViewDelegate {
var tableViewVC1: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableViewVC1.delegate = self // [CASE #1] self(VC1)에 있는 delegate 기능을 tableViewVC1이 사용하겠다.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { }
}
class VC2: UIViewController {
var tableViewVC2: UITableView!
let vc1 = VC1()
override func viewDidLoad() {
super.viewDidLoad()
tableViewVC2.delegate = vc1 // [CASE #2] vc1에 있는 delegate 기능(함수)를 tableViewVC2에서 사용하겠다.
tableViewVC2.dataSource = vc1
}
}
RxDelegateProxy GuideLine
ViewController가 2개가 존재하여 두개의 객체 사이에 이벤트를 Proxy를 통해 만들어진 것을 통해 통신하는 간단한 예제.
스토리보드를 활용하여 작업
🟠 ViewController.swift
//
// ViewController.swift
// RxSwiftDelegateExample
//
// Created by lgvv0908 on 2022/01/12
//
import UIKit
import RxSwift
import RxCocoa
final class ViewController: UIViewController, InputViewControllerDelegate {
private var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let storyBoard = UIStoryboard(name: "Main", bundle: .main)
guard let viewController = storyBoard.instantiateViewController(
withIdentifier: "InputViewController"
) as? InputViewController else { return }
viewController.rx.rx_deleagte.setForwardToDelegate(self, retainDelegate: false)
viewController.rx.rx_sendString
.bind(to: inputLabel.rx.text)
.disposed(by: disposeBag)
openButton.rx.tap
.throttle(.seconds(1), scheduler: MainScheduler.instance) // 버튼 클릭 후 1초동안 동일 이벤트 방출 안함
.subscribe(onNext: { [weak self] _ in
guard let self else { return }
self.present(viewController, animated: true, completion: nil)
}).disposed(by: disposeBag)
openSubjectButton.rx.tap
.bind { [weak self] in
guard let self else { return }
self.present(viewController, animated: true, completion: nil)
}.disposed(by: disposeBag)
viewController.inputStringSubject
.bind(to: inputLabel.rx.text)
.disposed(by: disposeBag)
}
// MARK: - UIComponents
@IBOutlet weak var inputLabel: UILabel!
@IBOutlet weak var openButton: UIButton!
@IBOutlet weak var openSubjectButton: UIButton!
}
🟠 InputViewController.swift
//
// InputViewController.swift
// RxSwiftDelegateExample
//
// Created by lgvv0908 on 2022/01/12
// Copyright © 2020 swieeft. All rights reserved.
//
import UIKit
import RxSwift
import RxCocoa
class InputViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var confirmButton: UIButton!
@IBOutlet weak var confirmSubjectButton: UIButton!
weak var delegate: InputViewControllerDelegate?
var disposeBag = DisposeBag()
var inputStringSubject = PublishSubject<String>() // 여기서 서브젝트를 갖고 있음
var inputString: Observable<String> { // 프로퍼티인데, inputStringSubject값을 Observable<String>값으로 받고 있음
return inputStringSubject.asObservable()
}
override func viewDidLoad() {
super.viewDidLoad()
confirmButton.rx.tap
.throttle(.seconds(1), scheduler: MainScheduler.asyncInstance)
.subscribe(onNext: { [weak self] _ in
guard let string = self?.textField.text else { return }
self?.dismiss(animated: true, completion: {
self?.delegate?.sendString?(string: string) // 프로토콜로 데이터 전달함
})
})
.disposed(by: disposeBag)
confirmSubjectButton.rx.tap
.debug("confirmSubjectButton")
.throttle(.seconds(1), scheduler: MainScheduler.asyncInstance)
.subscribe(onNext: { [weak self] _ in
guard let string = self?.textField.text else { return }
// self?.inputStringSubject.onNext(string) // 서브젝트로 방출함
self?.dismiss(animated: true, completion: {
self?.inputStringSubject.onNext(string) // 서브젝트로 방출함
print("string -> \(string)")
// self?.inputStringSubject.onCompleted()
})
})
.disposed(by: disposeBag)
textField.rx.controlEvent(.editingDidEndOnExit)
.debug("editingDidEndOnExit")
.subscribe(onNext: { [weak self] _ in
self?.view.endEditing(true)
})
.disposed(by: disposeBag)
}
}
'apple > RxSwift, ReactorKit' 카테고리의 다른 글
RxSwift ch 18. Table & Collection views (0) | 2022.01.18 |
---|---|
Extension Reactive (RxSwift) (1) | 2022.01.12 |
iOS RxStarScream 총정리 (0) | 2022.01.12 |
RxSwift 06 RxDataSources (0) | 2021.08.19 |
Ch13. Intermediate RxCocoa (0) | 2021.08.12 |