Coordinator 패턴 ?

minin·2022년 2월 7일
0

iOS Practices

목록 보기
2/4
post-thumbnail

👩‍💻 새롭게 공부하며 작성한 글이기 때문에 틀린 내용이 있을 수 있습니다! 내용에 관한 피드백은 언제나 환영입니다.🙌

🔖참고

SeSAC에서 서비스 단계 프로젝트를 하던 중 팀원이 coordinator 패턴을 아냐고 물은 적이 있다. '그사세 분들이 하시는 건가.. 오잉 뭐지?' 하고 넘어갔었는데, MVVM패턴에 대해서 검색을 하다가 마주치게 되었다!

간단하게 말하자면, 화면 전환을 조금 더 유연하게 사용하게 도와주는 것이라고 한다.

❗️Coordinator를 통해 화면 이동에 관한 로직을 따로 구현하고, ViewController에 쉽게 접근할 수 있도록 구성한다.

🙋 어떻게 사용하는데?

👉 protocol 을 활용한다!

  • 준비
  1. 화면을 전환하는 함수를 가지고 있는 coordinator프로토콜을 만든다.
  2. extension을 통해서, 화면 전환 함수를 구현한다.
  • 사용
  1. 화면 전환을 하는 뷰컨트롤러에서 coordinator delegate를 채택한다.
  2. 화면 전환을 원하는 시점에, coordinator가 가지고 있는 함수를 사용한다.

✔︎ protocol

protocol Coordinator {
  var parentCoordinator: Coordinator? { get set }
  var childCoordinators: [Coordinator] { get set }
  var navigationController: UINavigationController { get set }
  
  func start()

}
  • navigationConroller: 화면 전환에 필요한 UINavigationConroller
  • childCoordinator: 화면 전환 시 생성될 하위 Coordinator를 저장할 때 사용
    🙋coordinator를 생성하고 저장하지 않으면, 메모리에서 제거되지 않는다.
  • start: 실행될 함수: 실질적인 컨트롤러 생성, 화면 전환 및 종속성 주입의 역할을 한다.
class MainCoordinator: Coordinator {
    var parentCoordinator: Coordinator?
    var childCoordinators = [Coordinator]()
    var navigationController: UINavigationController

    init(navigationController: UINavigationController, parentCoordinator: Coordinator2?) {
        self.navigationController = navigationController
        self.parentCoordinator = parentCoordinator
    }

    func start() {
        let viewController = OnboardingViewController()
        navigationController.pushViewController(viewController, animated: true)
    }
    
    func pushToAuth() {
        let viewController = AuthViewController()
        navigationController.pushViewController(viewController, animated: true)
    }
    
    func pushToAuthSignUp() {
        let viewController = SignUpNicknameViewController()
        navigationController.pushViewController(viewController, animated: true)
    }
    
    func pushToAuthMain() {
        let viewController = MainTabBarController()
        navigationController.pushViewController(viewController, animated: true)
    }
}

✔︎ 사용

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
    var window: UIWindow?
    var coordinator: MainCoordinator?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let appWindow = UIWindow(frame: windowScene.coordinateSpace.bounds)
        appWindow.windowScene = windowScene
        
        let navigationController = UINavigationController()
        coordinator = MainCoordinator(navigationController: navigationController, parentCoordinator: coordinator)
        
        let startModeString = UserDefaults.standard.startMode
        let startMode = StartMode(rawValue: startModeString) ?? .onBoarding
        
        switch startMode {
        case .onBoarding:
            coordinator?.start()
        case .auth:
            coordinator?.pushToAuth()
        case .signUp:
            coordinator?.pushToAuthSignUp()
        case .main:
            print("go to main")
            coordinator?.pushToAuthMain()
        }

        appWindow.rootViewController = navigationController
        appWindow.makeKeyAndVisible()
        
        window = appWindow

    }
}

✔︎ 좋은 점은?
하나의 coordinator를 가지고, 여러 뷰컨에서 사용하기 때문에 수정이 필요하다면 coordinator에서만 로직을 수정하면 된다. 그래서∙∙∙

  1. 화면 전환 로직을 뷰컨에서 분리-> 비대해지는 것을 해결한다.
  2. MVVM 패턴과 같이 적용하면, 코드를 옮기는 작업이 수월해진다.

지금은 시작 화면 분기와 탭바(그런데 아주 많은 수정이 필요한..)에만 적용해 두었는데, 앞으로 리팩토링할 예정이다.
사실.. 저번에 switch문을 통해서 처리를 했던 이야기를 썼었는데, 며칠뒤 바로 coordinator로 바꾸었다.. 허허
이전에 쓴 글은 아래를 참고!
🔗 https://velog.io/@yoogail/siwtch문을-활용한-StartViewController-분기처리feat.-enum

profile
🍫 iOS 🍫 Swift

0개의 댓글