: ViewController의 역할 중 화면 전환 책임을 가져오는 것을 목표로 한다.

  1. ViewController끼리 서로 알지 못한다.

  2. 앱의 메인 흐름을 담당하는 AppCoordinator를 SceneDelegate 아래에 둔다.

  3. 앱의 주요 기능이나 흐름의 단위 별로 하위 Coordinator를 만든다.

구현

  1. 프로토콜 생성

    protocol Coordinator: AnyObject {
    		var childCoordinators: [Coordinator] { get set }
    		func start()
    }
    
  2. AppCoordinator 생성

    class AppCoordinator: Coordinator {
    
    		var navigationController = UINavigationController
    		var childCoordinators: [Coordinator] = []
    		
    		init(_ navigationController: UINavigationController) {
    				self.navigationController = navigationController
    		}
    		
    		func start() {
    				showMainFlow()
    		}
    		
    		func showMainFlow() {
    				let mainCoordinator = MainCoordinator(navigationController)
    				childCoordinators.append(mainCoordinator)
    				mainCoordinator.start()
    		}
    
  3. SceneDelegate 설정

    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    		var window: UIWindow?
    		
    		var appCoordinator: AppCoordinator?
    		
    		func scene(
    				_ scene: UIScene, 
    				willConnectTo session: UISceneSession,
    				options connectionOptions: UIScene.ConnectionOptions) {
    				
    				let navigationController = UINavigationController()
    				
    				guard let windowScene = (scene as? UIWindowScene) else { return }
    				
    				window = UIWindow(windowScene: windowScene)
    				window?.rootViewController = navigationController
    				window?.makeKeyAndVisible()
    				
    				appCoordinator = AppCoordinator(navigationController)
    				appCoordinator?.start()
    		}
    }
    
  4. 하위 Coordinator 생성

    protocol MainCoordinatorDelegate {
    		func didSomething()
    }
    
    class MainCoordinator: Coordinator {
    
    		weak var delegate: MainCoordinatorDelegate?
    		var navigationController = UINavigationController
    		var childCoordinators: [Coordinator] = []
    		var viewController: MainViewController
    		
    		init(_ navigationController: UINavigationController) {
    				self.navigationController = navigationController
    				self.viewController = MainViewController()
    		}
    		
    		func start() {
    				viewController.viewModel = MainViewModel(coordinator: self)
    				navigationController.viewControllers = [viewController]
    		}
    		
    		func showMainViewController() {
    				let mainCoordinator = MainCoordinator(navigationController)
    				childCoordinators.append(mainCoordinator)
    				mainCoordinator.start()
    		}
    		
    		func doSomething() {
    				delegate?.didSomething()
    		}
    }
    
  5. 이벤트 발생 시 Coordinator로 전달

    class MainViewModel {
    		weak var coordinator: MainCoordinator?
    		
    		...
    		
    		func buttonTapped() {
    				coordinator?.doSomething()
    		}
    }
    
  6. AppCoordinator와 MainCoordinator 연결

    class AppCoordinator: Coordinator {
    		...
    		
    		func showMainFlow() {
    				let mainCoordinator = MainCoordinator(navigationController)
    				mainCoordinator.delegate = self
    				...
    		}
    }
    
    extension AppCoordinator: MainCoordinatorDelegate {
    		func didSomething() {
    				showSubFlow()
    		}
    }