관리 메뉴

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

[iOS - swift] 2. MVC with Coordinator 예제 코드 본문

Architecture (swift)/MVC (with coordinator)

[iOS - swift] 2. MVC with Coordinator 예제 코드

jake-kim 2021. 4. 29. 23:48

MVC with Coordinator

MVC with Coordinator 핵심

  • MVC는 Coordinator의 존재를 모르며, 어느 화면으로 이동하는지 모르는 상태
    • ViewController에서 routeToLogin과 같이 호출하면 안되도, finishLoad()와 같이 호출
  • Coordinator를 자유롭게 갈아 끼울수 있는 모듈화 구조
  • DI는 Coordinator에서 실행

MVC 2개 준비

  • FirstViewController
  • SecondViewController
  • 코드

Coordinator 적용

  • Coordinator 추가
import UIKit

protocol FirstControllerDelegate: AnyObject {
    func run()
    func onAction()
}

final class Coordinator: FirstControllerDelegate {
    let window: UIWindow
    var navigationController: UINavigationController?

    lazy var firstViewController: FirstViewController = {
        let controller = FirstViewController()
        controller.coordinator = self
        return controller
    }()

    lazy var secondViewController: SecondViewController = {
        let controller = SecondViewController()
        controller.coordinator = self
        return controller
    }()

    init(window: UIWindow) {
        self.window = window
    }

    func run() {
        navigationController = UINavigationController(rootViewController: firstViewController)
        window.rootViewController = navigationController
        window.makeKeyAndVisible()
    }

    func onAction() {
        navigationController?.pushViewController(secondViewController, animated: true)
    }
}
  • FirstViewController, SecondViewController에 각각 delegate 선언
// FirstViewController.swift

weak var coordinator: FirstControllerDelegate?
// SecondViewController.swift

weak var coordinator: FirstControllerDelegate?
  • AppDelegate에 Coordinator 적용
    • 전역변수에 coordinator를 선언한 이유: strong reference를 유지하기 위함
    • 만약 전역변수에 coordinator를 선언하지 않을 경우, AppDelegate 클래스가 종료되면 coordinator도 메모리에서 해제되어, FirstViewController에서 Coordinator호출해도 동작 x
// AppDelegate.swift

class AppDelegate: UIResponder, UIApplicationDelegate {

    var coordinator: Coordinator?
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        let window = UIWindow(frame: UIScreen.main.bounds)
        self.window = window
        coordinator = Coordinator(window: window)
        coordinator?.run()
        return true
    }

}

확장

  • 새로운 화면전환은 FirstControllerDelegate와 같이 다양하게 만들고, Coordinator에 extension으로 추가하는 형식으로 구현
Comments