티스토리 뷰
이전까지 하게 되면 빌드는 되지만 검은 화면이 나오는 프로젝트를 만들게 될겁니다.
그러면 이제 하나씩 만들어 보도록 할게요.
이전글
2020/10/03 - [Mobile/iOS] - RIBs를 이용한 개발 - 2. RIBs Setting.
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
'Mobile > iOS' 카테고리의 다른 글
UIWindowSceneDelegate란 무엇인가? 어떨때 필요한가? (0) | 2020.12.19 |
---|---|
RIBs를 이용한 개발 - 4. NextPage (0) | 2020.10.06 |
RIBs를 이용한 개발 - 2. RIBs Setting. (0) | 2020.10.03 |
RIBs를 이용한 개발 - 1. RIBs란? (0) | 2020.10.03 |
iOS background push에 관해서 (0) | 2020.10.03 |
- Total
- Today
- Yesterday
- Python
- centos8
- Java
- Codable
- go
- tomcat
- github
- CentOS
- android
- cocoapods
- ubuntu
- Xcode
- docker
- golang
- war
- ios
- SWIFT
- enum
- intellij
- nodejs
- Kotlin
- Windows
- Linux
- Spring
- rxswift
- Gradle
- php
- git
- windows10
- MySQL
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |