티스토리 뷰

Mobile/iOS

RIBs를 이용한 개발 - 3. Main RIBs

out of coding 2020. 10. 4. 00:41

이전까지 하게 되면 빌드는 되지만 검은 화면이 나오는 프로젝트를 만들게 될겁니다.

그러면 이제 하나씩 만들어 보도록 할게요.

 

이전글

2020/10/03 - [Mobile/iOS] - RIBs를 이용한 개발 - 2. RIBs Setting.

 

RIBs를 이용한 개발 - 2. RIBs Setting.

이전 글에서 RIBs가 무엇인지에 대해서 알아보았습니다. 2020/10/03 - [Mobile/iOS] - RIBs를 이용한 개발 - 1. RIBs란? RIBs를 이용한 개발 - 1. RIBs란? 저는 Rx를 이용한 MVVM을 기본으로 개발합니다. 이것도..

mrgamza.tistory.com

Sources > Scene > MainRIB 만들기

프로젝트 Group을 만들어주세요

순서를 지키지 않아도 되지만 순서대로 만드는게 편안하게 만드는 방법입니다.

MainViewController

Presenter에 사용되는 protocol과 ViewController를 정의합니다.

MVVM에 익숙하신 분들이라면 Action은 Input과 같고 Handler는 Output과 같습니다.

즉, Action은 다른곳에 전달하는 용도이고 Handler는 ViewController에서 처리하여 주어야 하는 부분입니다.

Router에서 화면 전환등에 사용 하게 될 ViewControllable도 정의 하여 줍니다.

import RIBs
import SnapKit
import RxSwift
import RxCocoa

// MARK: - Presenter

protocol MainPresentableAction: class {
    var didClickButton: Observable<Void> { get }
}

protocol MainPresentableHandler: class {
    var buttonText: Observable<String> { get }
}

protocol MainPresentable: Presentable {
    var action: MainPresentableAction? { get set }
    var handler: MainPresentableHandler? { get set }
}

// MARK: - ViewControllable

protocol MainViewControllable: ViewControllable {
    func present(_ viewController: ViewControllable, animated: Bool)
}

// MARK: - ViewController

final class MainViewController: UIViewController, MainPresentable {
    
    // MARK: - UI Components
    
    private lazy var button: UIButton = {
        let button = UIButton()
        button.titleLabel?.numberOfLines = 0
        button.titleLabel?.textAlignment = .center
        return button
    }()
    
    // MARK: - Properties
    
    private let disposeBag = DisposeBag()
    
    // MARK: - Presentable
    
    var action: MainPresentableAction?
    var handler: MainPresentableHandler?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupView()
        bindPresentable()
    }
    
    private func setupView() {
        view.addSubview(button)
        button.snp.makeConstraints { maker in
            maker.center.equalToSuperview()
        }
    }
    
    private func bindPresentable() {
        action = self
        
        guard let handler = handler else { return }
        handler.buttonText
            .bind(to: button.rx.title(for: .normal))
            .disposed(by: disposeBag)
    }
}

extension MainViewController: MainPresentableAction {
    var didClickButton: Observable<Void> {
        return button.rx.tap.asObservable()
    }
}

extension MainViewController: MainViewControllable {
    func present(_ viewController: ViewControllable, animated: Bool) {
        print("present need")
    }
}

MainInteractor

Router와 Presenter를 연결하는 역할을 하기 때문에 Routing 관련된 protocol과 Interractable에 대한 code를 넣어줍니다.

import RIBs
import RxSwift
import RxCocoa

// MARK: - Routing

protocol MainRouting: ViewableRouting {
    func presentNext()
}

// MARK: - Interactable

protocol MainInteractable: Interactable {
    var router: MainRouting? { get set }
}

// MARK: - Interactor

final class MainInteractor: PresentableInteractor<MainPresentable>,
                            MainInteractable {
    private let buttonTextRelay: BehaviorRelay<String>
    
    weak var router: MainRouting?
  
    init(buttonText: String,
         presenter: MainPresentable) {
        buttonTextRelay = .init(value: buttonText)
        super.init(presenter: presenter)
        presenter.handler = self
    }
    
    override func didBecomeActive() {
        super.didBecomeActive()
        setup()
    }
    
    private func setup() {
        presenter.action?.didClickButton
            .bind { [weak self] in
                self?.router?.presentNext()
            }
            .disposeOnDeactivate(interactor: self)
    }
}

extension MainInteractor: MainPresentableHandler {
    var buttonText: Observable<String> {
        return buttonTextRelay.asObservable()
    }
}

MainRouter

Interactor에서 받은 신호를 통해서 viewController에 바로 정보를 전달하도록 만들어 줍니다.

import RIBs

final class MainRouter: LaunchRouter<MainInteractable, MainViewControllable> {
    override init(interactor: MainInteractable,
                  viewController: MainViewControllable) {
        super.init(interactor: interactor, viewController: viewController)
        interactor.router = self
    }
}

extension MainRouter: MainRouting {
    func presentNext() {
        print("show")
        // 나중에 여기에 present를 채울겁니다.
    }
}

MainBuilder

외부에서 주입받는 Dependency를 넣어주고 이것을 통해서 View, Interactor, Router를 만들어주는 역할을 합니다.

import RIBs

// MARK: - Component

protocol MainDependency: Dependency {
    var buttonText: String { get }
}

final class MainComponent: MainDependency {
    var buttonText: String { "Hello, RIBs\nClick Button!" }
}

final class MainComponentTest: MainDependency {
    var buttonText: String { "Test" }
}

// MARK: - Builder

protocol MainBuilable: Buildable {
    func build() -> LaunchRouting
}

final class MainBuilder: Builder<MainDependency>, MainBuilable {
    
    init() {
        super.init(dependency: MainComponent())
    }
    
    func build() -> LaunchRouting {
        let viewController = MainViewController()

        let interactor = MainInteractor(buttonText: dependency.buttonText,
                                        presenter: viewController)
        
        return MainRouter(interactor: interactor,
                          viewController: viewController)
    }
}

이렇게 하면 정상적으로 화면에 Button이 하나 나오고

Hello, RIBs

Click Button!

이렇게 노출되고 클릭을 하면 click이 나오게 될겁니다.

AppDelegate

이것을 추가한다는것을 잊고 있었습니다.

import UIKit
import RIBs

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
    
    lazy var launchRouter: LaunchRouting = MainBuilder().build()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        launchRouter.launch(from: window!)
        return true
    }
}

 

소스는 올려두었는데 tag로 구분하여 두었으니 확인해보세요

github.com/outofcode-example/iOS-RIBsExample/tree/OnlyMain

 

outofcode-example/iOS-RIBsExample

uber RIBs example. Contribute to outofcode-example/iOS-RIBsExample development by creating an account on GitHub.

github.com

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함