뷰끼리 데이터 어떻게 넘겨요...?

JuneHyeok Hong·2023년 4월 25일
0

클린 아키텍쳐

목록 보기
3/3

다른 ViewController로 데이터 어떻게 넘기지?

지금까지 MVC 패턴에서 VC가 뷰를 짜는것 이외에 모든 로직과 navigation control을 책임졌기 때문에 다른 VC로 데이터를 넘길 때는 큰 고민없이 프로퍼티 접근을 통해 push 되는 VC에 데이터를 넘기고 있었다.
하지만 MVVM에서는 버튼 클릭의 이벤트도 ViewModel의 Input으로 넘어가기 때문에 다른 VC로 push 되는 coordinator의 활용과 push 된 VC에 데이터를 넘기는 작업을 ViewModel에서 수행해야 했다.

어떻게 구현했어?

일단 나는 아래 사진과 같이 프로젝트를 구성하고 싶었다.
좋다! 일단 하나의 VC에서 발생되는 로직 처리, 네트워킹 처리는 어느정도 이해가 되었고 View, ViewController, ViewModel, UseCase 를 만들어 구현했다.

만약 A -> B로 push 될 때 어떻게 데이터를 전달해야 할까?

  1. A VC에서 버튼(뷰 푸쉬) 클릭 이벤트 Input 형태로 A ViewModel에 전달
  2. A ViewModel에 만들어둔 "validUserEmail: String" 값을 뷰 푸쉬 로직에 넣어서 뷰 푸쉬 구현 (애초에 보내야할 데이터는 ViewModel에 있다.)
    -> 여기서 나는 A Coordinator를 만들어뒀기 때문에 A Coordinator 활용
  3. A ViewModel에서 A Coordinator에 구현해둔 뷰 푸쉬 함수를 호출하며 B Coordinator의 start 함수 호출 됨,
    여기서 B Coordinator의 프로퍼티로 "validUserEmail: String" 값 전달
    // A Coordinator의 뷰 푸쉬 함수
    func startWelcomeView(userEmail: String) {
        let coordinator = BCoordinator(navigationController: navigationController)
        coordinator.userEmail = userEmail
        start(childCoordinator: coordinator)
    }
  1. B Coordinator의 start함수에서 B VC를 푸쉬하는데 이때 B ViewModel와 함께 전달
    override func start() {
        guard let userEmail = userEmail else { return }
        let BViewModel = BViewModel(coordinator: self, userEmail: userEmail)
        let viewController = BViewController(viewModel: BViewModel)
        navigationController.pushViewController(viewController, animated: true)
    }
  1. B ViewModel의 Output으로 ((String) -> Void) 형태의 클로저를 만들고
    B bind() 함수를 활용해 클로저를 옵저빙해둔다.
    이때 B ViewModel로 들어오는 "validUserEmail: String" 값을
    Output 클로저로 B VC에 전달한다.

아래 PR을 보면서 이해하면 좋을것 같다.

https://github.com/GO-SOPT-iOS-Part/HongJuneHuke/pull/8

결론은?

사실 프로퍼티로 접근하는 방법 외에도 Notifiction을 활용하거나 closure 또는 Protocol을 사용할 수 있겠지만.. 아직 어떤 방법이 더 간결하고 좋을지? (좋다는 기준이 너무 다양하지만..)
좀 더 고민해봐야겠다.

0개의 댓글