티스토리 뷰

Swift

[Swift] Coordinator Pattern

진태우 2021. 1. 31. 19:41

읽기 쉬운 코드 만들기를 목적으로 공부한 내용 중 Coordinator Pattern에 대해 정리해 보려고 합니다.

 

코디네이터 패턴은 UIViewController 간의 흐름을 제어하기 위한 패턴입니다.

앱의 흐름을 담당하는 별도의 객체를 만들어 사용하기 때문에 UIViewController와는 독립적이며, 재사용에 용이합니다.

 

- 수행 기능

1. 화면 전환에 필요한 인스턴스 생성( UIViewController, ViewModel 등.. )

2. 생성한 인스턴스의 종속성 주입(DI)

3. 생성된 UIViewController의 화면 전환 (push or present)

 

아래와 같이 컨트롤러 간의 화면 전환하는 코드를 UIViewController에서 많이 작성했을 것입니다.

let vc = HomeViewContrller()
navigationController?.pushViewController(vc, animated: true)

 

여러 곳에서 해당 컨트롤러로 화면 전환을 해야할 경우, 위와 같은 코드를 여러 곳에서 사용해야 할 것입니다.

만약 컨트롤러의 이름이나 추가적으로 값을 전달해야 할 경우에는 해당 코드를 모두 찾아서 변경해야겠죠.

코디네이터를 사용하면 HomeViewController로 화면 전환하는 코디네이터를 만들어 재사용함으로써, 사용하기도 쉽고 유지보수에도 좋을 것입니다.

물론 UIViewController에서 화면 전환에 대한 로직이 제거되어 좀 더 보기 쉽게 되겠죠! 👍

 

바로 코드로 GOGO 😎

아래 순서대로 코드 작성을 해보겠습니다.

 

1. Coordinator 프로토콜 구현

2. AppCoordinator 구현 ( AppDelegate에서 사용될 Coordinator)

3. HomeCoordinator 구현 ( 초기 화면에 대한 Coordinator)

AppDelegate에서 AppCoordinator 생성


 

Coordinator 프로토콜 구현

protocol Coordinator: AnyObject {
    
    var presenter: UINavigationController { get set }    // 1
    
    var childCoordinators: [Coordinator] { get set }    // 2
    
    func start()    // 3
}

간단히 설명하면, 

1. presenter는 화면 전환에 필요한 UINavigationController 입니다.

presenter.pushViewController(vc, animated: true)          // push
presenter.present(vc, animated: true, completion: nil)    // present

2. childCoordinators는 화면 전환시 생성될 하위 Coordinator를 저장할 때 사용합니다.

    coordinator 생성후 저장하지 않으면, 메모리에서 제거되기 때문에 꼭 저장해야합니다.

3. start 함수는 컨트롤러 생성, 화면 전환 및 종속성 주입의 역할을 합니다.


 

AppCoordinator 구현

class AppCoordinator: NSObject, Coordinator {
    
    var presenter: UINavigationController

    var childCoordinators: [Coordinator]

    let window: UIWindow
    
    
    init(window: UIWindow) {
        self.window = window
        self.presenter = UINavigationController()
        self.childCoordinators = []
    }
    
    func start() {
        window.rootViewController = presenter    // 1
        
        let coordinator = HomeCoordinator(presenter: presenter)    // 2        
        childCoordinators.append(coordinator)    // 3
        coordinator.start()    // 4
        
        window.makeKeyAndVisible()
    }
    
}

AppCoordinator는 앱 시작시 초기 컨트롤러를 연결하기 위한 coordinator 입니다.

AppDelegate에서 전달받은 window의 rootViewController와 HomeViewController를 연결하기 위한 내용입니다.

 

1. 초기화 메소드에서 생성한 UINavigationController를 rootViewController로 설정

2. rootViewController로 설정된 presenter를 HomeCoordinator에 생성자 파라미터로 전달하여, HomeViewController와 연결되게 합니다.

3. coordinator가 메모리에서 사라지지 않기 위해서는 인스턴스를 저장해야 합니다.

4. start()를 호출하여 HomeViewController 인스턴스를 초기화 합니다.


 

HomeCoordinator 구현

class HomeCoordinator: NSObject, Coordinator {
    
    var presenter: UINavigationController
    
    var childCoordinators: [Coordinator]

    var viewModel: HomeViewModel?
    

    init(presenter: UINavigationController, viewModel: HomeViewModel? = HomeViewModel()) {
        self.presenter = presenter
        self.childCoordinators = []
        self.viewModel = viewModel
    }
    
    func start() { 
        let homeView = HomeViewController.instantiate()
        homeView.viewModel = viewModel
        presenter.pushViewController(homeView, animated: false)
    }
    
}

HomeViewController로 화면 전환할 수 있는 Coordinator 입니다.

필요에 따라 viewModel이나 필요한 값을 주입할 수 있습니다.


 

AppDelegate에서 AppCoordinator 생성

앱의 초기 화면인 HomeViewController를 연결할 준비는 끝났습니다.

아래 코드와 같이 AppCoordinator 생성 후 start 메소드만 실행하면 간단하게 연결됩니다~!!

var window: UIWindow?
    
var appCoordinator: AppCoordinator?


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    appCoordinator = AppCoordinator(window: window!)
    appCoordinator?.start()
    
    return true
}

 

 

- 마무리

화면 전환에 대한 코드를 따로 관리하도록 변경하면서, 재사용과 유지보수에 대해서 편하다는 느낌을 받았습니다.

아직 미숙하지만, 좀 더 사용하면서 나의 스타일에 맞게 수정하면 더 사용하기 좋을 것 같습니다.

UITabBarController를 연결하거나, childCoordinator에 추가된 인스턴스들을 해제하는 내용등 포스팅에 정리하지 못한 내용들은 GitHub Repository에 업로드되어 있습니다. 👻 👻 👻

 

 

- Reference

https://khanlou.com/2015/10/coordinators-redux/

https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps

https://somevitalyz123.medium.com/coordinator-pattern-with-tab-bar-controller-33e08d39d7d

http://labs.brandi.co.kr/2020/06/16/kimjh.html

https://dev-wd.github.io/swift/coordinator/

'Swift' 카테고리의 다른 글

[Swift] Closures  (0) 2021.02.21
[Swift] xib 파일로 View 관리하기  (0) 2020.09.28
[swift] xib를 이용한 alertView 만들기  (0) 2020.07.19
[swift] UIButton에 클로저를 추가해 보았습니다.  (0) 2020.07.14
[swift] AssociatedObject  (0) 2020.07.11
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함