Repository navigation
MainView
WooSeok Suh edited this page Jul 5, 2021
·
8 revisions
by Seok
- MainView 하단의 ViewController 이동 Button을 UIButton으로 생성하고 Horizontal StackView에 배치
- AutoLayout 확인 (iPod touch, 8, 11, 12)
Button의 다형성 구현을 위하여 ButtonController 및 ButtonMapper 객체 생성
- 각 Button Touch시 어떤 Button이 눌리는지 구분 기능 구현 완료
- 해당 기능 바탕으로 이동할 ViewController와 Mapping 예정
import UIKit
enum ViewControllerType: CaseIterable {
case giftVC
case advertiseVC
case rankVC
case itemVC
}
final class ButtonMapper {
private var map: [UIButton: ViewControllerType]
init(from buttons: [UIButton]) {
self.map = Dictionary(uniqueKeysWithValues: zip(buttons, ViewControllerType.allCases))
}
subscript(button: UIButton) -> ViewControllerType? {
return map[button]
}
}
final class ButtonController: NSObject {
@IBOutlet var moveToVCButtons: [UIButton]!
private var moveToVCMapper: ButtonMapper?
private var buttonTouchedHandler: (ViewControllerType) -> ()
override init() {
buttonTouchedHandler = { _ in }
}
func setupButton() {
self.moveToVCMapper = ButtonMapper(from: moveToVCButtons)
}
@IBAction func buttonTouched(sender: UIButton) {
guard let vc = moveToVCMapper?[sender] else { return }
buttonTouchedHandler(vc)
}
func bind(action: @escaping (ViewControllerType) -> ()) {
self.buttonTouchedHandler = action
}
}이때 SceneCoordinator 생성하여 진행할지 회의 필요 -> SceneCoordinator로 구현하기로 협의하여 객체생성
import Foundation
import RxSwift
import RxCocoa
final class SceneCoordinator: SceneCoordinatorType {
private var window: UIWindow
private var currentVC: UIViewController
required init(window: UIWindow) {
self.window = window
currentVC = window.rootViewController!
}
@discardableResult
func transition(to scene: Scene, using style: TransitionStyle, animated: Bool) -> Completable {
let subject = PublishSubject<Void>()
let target = scene.instantiate()
switch style {
case .root:
currentVC = target
window.rootViewController = target
subject.onCompleted()
case .fullScreen:
target.modalPresentationStyle = .fullScreen
currentVC.present(target, animated: animated) {
subject.onCompleted()
}
currentVC = target
case .modal:
currentVC.present(target, animated: animated) {
subject.onCompleted()
}
currentVC = target
}
return subject.ignoreElements().asCompletable()
}
@discardableResult
func close(animated: Bool) -> Completable {
let subject = PublishSubject<Void>()
if let presentingVC = self.currentVC.presentingViewController {
self.currentVC.dismiss(animated: animated) {
self.currentVC = presentingVC
subject.onCompleted()
}
} else {
subject.onError(TransitionError.unknown)
}
return subject.ignoreElements().asCompletable()
}
}ViewController가 ViewModel로 Button이 가지고있는 ViewControllerType을 넘기면 VC 이동기능 구현
- CommonViewModel이 가지고 있는 SceneCoordinator 객체 활용
import Foundation
class MainViewModel:CommonViewModel {
func makeMoveAction(to viewController: ViewControllerType) {
switch viewController {
case .giftVC:
let giftViewModel = GiftViewModel(sceneCoordinator: self.sceneCoordinator)
let giftScene = Scene.gift(giftViewModel)
self.sceneCoordinator.transition(to: giftScene, using: .modal, animated: true)
case .advertiseVC:
let advertiseViewModel = AdvertiseViewModel(sceneCoordinator: self.sceneCoordinator)
let advertiseScene = Scene.ad(advertiseViewModel)
self.sceneCoordinator.transition(to: advertiseScene, using: .fullScreen, animated: true)
case .rankVC:
let rankViewModel = RankViewModel(sceneCoordinator: self.sceneCoordinator)
let rankScene = Scene.rank(rankViewModel)
self.sceneCoordinator.transition(to: rankScene, using: .modal, animated: true)
case .itemVC:
let itemViewModel = ItemViewModel(sceneCoordinator: self.sceneCoordinator)
let itemScene = Scene.item(itemViewModel)
self.sceneCoordinator.transition(to: itemScene, using: .modal, animated: true)
}
}
}추후 로직에 따라 Storage 등의 추가 객체가 필요하면 CommonViewModel의 init에 주입하여 SceneDelegate에서 넣어주면 쉽게 코드 변경 가능
- 이때도 마찬가지로 Protocol활용하여 다형성 구현가능
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let coordinator = SceneCoordinator(window: window!)
let mainViewModel = MainViewModel(sceneCoordinator: coordinator)
let mainScene = Scene.main(mainViewModel)
coordinator.transition(to: mainScene, using: .root, animated: false)
}created by 우송