iOS MVVM base protocol 작업

김개발소발·2022년 9월 5일
0

MVVM

목록 보기
2/2

MVVM으로 전환하기 전에 프로토콜로 MVVM 패턴의 기본적인 구조를 정의해보겠습니다.

기본적인 구조를 잡는데 이 포스트를 참고했습니다.

1. BaseProtocol

1-1. View Model Protocol

먼저 뷰모델 계층을 추상화할 ViewModelProtocol을 정의합니다.

protocol ViewModelProtocol {
    associatedtype View: ViewProtocol
    var view:View? { set get }
 }

ViewModelProtocol은 associatedtype View은 뒤에서 나올 ViewProtocol의 상세 타입을 정의합니다.
assotiatedtype으로 정의된 View는 뷰모델의 데이터를 시각적으로 보여줄 뷰를 참조합니다.

1-2. View Protocol

다음으로 뷰 계층을 추상화할 ViewProtocol을 정의합니다.
ViewProtocol은 assocatatedtype ViewModel을 특정 뷰모델의 타입으로 참조하게 됩니다.
bindViewModel() 함수는 뷰모델과 뷰가 화면에 보여지고 나서 초기화하는 역할을 하는 함수로 선언했습니다.

protocol ViewProtocol {
    associatedtype ViewModel:ViewModelProtocol
    var viewModel:ViewModel? { set get }
    func bindViewModel()
}

2. View 초기화

초기화를 위한 코드는 ViewProtocol이 UIViewController에서 채택되었을 때만 호출할 수 있도록 extension을 정의합니다.

2-2.View Protocol

// UIViewController에서 채택되었을 때
extension ViewProtocol where Self:UIViewController {
    mutating func bind(viewModel: Self.ViewModel) {
        self.viewModel = viewModel
        loadViewIfNeeded()
        
        bindViewModel()
    }
}

extension의 조건을 Self:UIViewController로 정의해 bind(viewModel:Self.ViewModel)함수가 UIViewController에서만 정의되도록 선언합니다.
그리고 이 함수에서 앞에 선언된 bindViewModel()을 호출해 뷰가 생성되고 나서 바로 뷰 모델과 바인드합니다.

2-2. View Model Protocol

// ViewProtocol이 UIViewController에서 채택되었을 때
extension ViewModelProtocol where View:UIViewController {
    mutating func intializeScene() -> View {
    	// View 초기화
        var view = View.init()
        
        self.view = view
        
        /*
        뷰를 초기화하고 나서 자신의 타입이 
        View의 ViewModel 타입과 동일한지 캐스팅 후 
        뷰 모델을 참조하고 있는 뷰에 바인딩합니다.
        */
        if let viewModel = self as? Self.View.ViewModel {
            view.bind(viewModel: viewModel)
        }
        
        return view
    }
}

3. 적용

3-1. MainViewController

MainViewController라는 UIViewController를 정의한다고 가정하겠습니다.
MainViewController을 추상화할 MainViewProtocol을 먼저 정의하겠습니다.

protocol MainViewProtocol:ViewProtocol {
    
}

MainViewController의 ViewModel을 추상화할 MainViewModel의 프로토콜 MainViewModelProtocol을 정의합니다.

3-2. MainViewModel

MainViewController의 ViewModel을 추상화할 MainViewModel의 프로토콜 MainViewModelProtocol을 정의합니다.
MainViewModel을 정의할 때 ViewModelProtocol.View의 타입을 MainViewProtocol로 지정합니다.

protocol MainViewModelProtocol: ViewModelProtocol where View:MainViewProtocol {
}

3-3. 상세화(프로토콜 채택)

ViewController

// 편의상 UIViewController 상속 부분은 제외
class MainUIViewController: MainViewProtocol {
	typealias ViewModel = MainViewModel
    var viewModel: MainViewModel?
    func bindViewModel() {
    }
	...
}

ViewModel

class MainViewModel: MainViewModelProtocol {
	typealias View = MainUIViewController
}

3-4. 초기화

var vm = MainViewModel()
let vc = vm.intializeScene()

self.present(vc, animated:true)
profile
사람들 속에 숨어사는 INTJ 성향을 가진 개발자

0개의 댓글