Interface

  1. finishDelegate: 부모 코디네이터에 자식 코디네이터의 라이프 사이클이 종료되었음을 전달
    1. 부모 코네이터에 할당
  2. navigationController: 코디네이터는 하나의 navVC를 소유
  3. childCoordinators: 현재 렌딩되어 있는 자식 코디네이터 배열
  4. type: Flow 타입
  5. start(): Flow의 시작 지점 진입 로직
  6. finish(_ nextFlow: ChildCoordinatorTypeProtocol?): Flow의 종료 시점 로직
    1. 다음 Flow가 없을 수도 있기 때문에 옵셔널로 처리한다.
// Coordinator
protocol Coordinator: AnyObject {
    // 1. 부모 코디네이터에 할당
    var finishDelegate: CoordinatorFinishDelegate? { get set }
    
    // 2. 각 코디네이터는 하나의 nav를 갖는다
    var navigationController: UINavigationController { get set }
    init(_ navigationController: UINavigationController)
    
    // 3. 현재 살아있는 자식 코디네이터 배열 (주로 1개)
    var childCoordinators: [Coordinator] { get set }
    
    // 4. Flow 타입
    var type: CoordinatorType { get }
    
    // 5. Flow 시작 시점 로직
    func start()
    
    // 6. Flow 종료 시점 로직. (extension에서 선언)
    func finish(_ nextFlow: ChildCoordinatorTypeProtocol?)
}

// 앱 내에서 어떤 flow를 담당하는지 정의한다
enum CoordinatorType {
    // App
    case app
    
    // Auth
    case auth
    
    // Home
    case tabBar
}

// 각 코디네이터의 자식 코디네이터 타입을 저장. (enum)
// 모든 enum을 매개변수로 받기 위한 프로토콜. (제네릭으로 받을 예정)
protocol ChildCoordinatorTypeProtocol {

}

// 자식 코디네이터의 라이프 사이클이 종료되었음을 부모에게 전달
protocol CoordinatorFinishDelegate: AnyObject {
    func coordinatorDidFinish(childCoordinator: Coordinator, nextFlow: ChildCoordinatorTypeProtocol?)
}

// finish() 구현체 => 모든 코디네이터에서 동일하기 때문에 미리 선언
extension Coordinator {
    func finish(_ nextFlow: ChildCoordinatorTypeProtocol?) {
        // 1. 자식 코디 다 지우기
        childCoordinators.removeAll()
        
        // 1.3 네비게이션에서 push로 띄운 vc 모두 제거
        navigationController.viewControllers.removeAll()
        
        // 1.5 네비게이션에서 present로 띄운 vc 모두 제거 (??)
        navigationController.presentedViewController?.dismiss(animated: false)
        
        // 2. 부모 코디에게 알리기
        finishDelegate?.coordinatorDidFinish(
            childCoordinator: self,
            nextFlow: nextFlow
        )
    }
}