IOS/iOS

[TIL] iOS. MVVM without Rxswift

https://riptutorial.com/ko/ios/example/27354/%EB%A6%AC-%EC%95%A1%ED%8B%B0%EB%B8%8C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4%EC%97%86%EB%8A%94-mvvm

 

iOS - 리 액티브 프로그래밍이없는 MVVM | ios Tutorial

ios documentation: 리 액티브 프로그래밍이없는 MVVM

riptutorial.com

MVVM 공부하고 아무리 쳐다봐도 이해하기 힘든 부분이 생겨요... 왜죠?

  • MVVM이란 개념을 듣고 구현하려하고 이해하려고 노력한지 약 한달정도가 되었는데요 이리저리 블로그를 찾아보고 했었는데 갈수록 개념을 정리하는데 어려움이 생겼던것 같습니다. 제가 이해하려고 한부분은 명확하게 3가지 파트가 나뉘어야 하는데 코드 예제를 보아도 아 이렇구나 라고 이해해도 막상 구현하려하면 실제 데이터 즉 모델은 주로 네트워크상에서 받아오기 때문에 이런것은 어떻게 구현해야 하나... 계속 어려움이 생겼죠

  • 사실 이 그림을 보면 꾀나 간단한것 같습니다 뷰는 뷰모델을 잡아 정보를 받아오고 , 뷰모델은 모델을 잡아 정보를 받아오고 그저 잡고있는 샘이죠. 따라서 MVVM이라는 개념을 이해하려면 저 데이터를 잡는다. 즉 바인딩하거나 옵저빙 한다라는 개념을 알고 코드상에 어떻게 구현되어있는지를 이해해야 했습니다. 근데 옵저빙을 한다는것은 RxSwift로 구현하기가 쉽다고 하더라구요 그런데 저는 아직 Rxswift를 시작할 단계는 아니라는 생각에 MVVM without Rxswift 를 검색하고 링크한 페이지를 찾게 되었습니다.

 MVVM 구현에 필요한 핵심 클래스

class Dynamic<T> {
    typealias Listener = (T) -> Void
    var listener: Listener?
    
    func bind(_ listener: Listener?) {
        self.listener = listener
    }
    
    func bindAndFire(_ listener: Listener?) {
        self.listener = listener
        listener?(value)
    }
    
    var value: T {
        didSet {
            listener?(value)
        }
    }
    
    init(_ v: T) {
        value = v
    }
}
  • 위의 코드를 처음봤을때는 아무것도 몰랐습니다. 단지 동사를 보고 유추할수 있죠 bind 응... 잡는거구나 bindAndFire 잡고 쏘는거구나... 
  • 근데 코드가 하는 역할은 알았지만 어떻게 작동하는지는 이해할수없었습니다. 왜냐 typealias 라는것을 처음보았고 인스턴스에 클로저를 저장한다는 개념이 생소해서 너무나 어려웠습니다. 알고나서는 간단한 개념인것을 알았지만 처음에는 너무 어렵더라구요 그래서 저처럼 RxSwift가 아닌 Swift로만 MVVM을 위한 데이터 바인딩을 하시려는 분들중에 이해하기 어려운 분들이 있을까해서 작성하게 되엇습니다.
  • 위에서 typealias라는 개념은 새로운 타입을 선언하는 것입니다 마치 String은 문자열 타입이야! 라는 것과 같은 개념이죠 따라서 Listerner라는 타입은 클로저야! 라고 하는것과 같습니다
  • 그 아래 listener라는 인스턴스는 옵셔널 클로저 타입 인스턴스입니다. 쉽게말하면 listener는 클로저 코드를 담고있는 샘이죠
  • bind는 말그대로 잡는다는 겁니다 링크에 예시로 나온 코드를 보시면 
func bindViewModel() {
        if let viewModel = viewModel {
            viewModel.helloText.bind({ (helloText) in
                DispatchQueue.main.async {
                    // When value of the helloText Dynamic variable
                    // is set or changed in the ViewModel, this code will
                    // be executed
                    self.helloLabel.text = helloText
                }
            })
        }
    }
  • 이런식으로 함수가 생성된것이 보이시죠 바인드뒤로 클로저가 나오고 이 클로저는 helloText라는 매개변수가 들어가서 self.helloLabel.text의 값을 바꾸는 클로저입니다. 
  • 이렇게 bind함수를 이용해서 뒤에 클로저를 사용하면 Dynamic클래스의 bind는 클로저를 listner에 저장해둡니다.( 이렇게 지정된 클로저는 사용자의 필요에의해 지정되는 코드입니다. )
  • Dynamic클래스의 이니셜라이저는 value인스턴스를 생성하는데 이 인스턴스는 값이 바뀔때마다 listener?(value) 이 코드에 의해서 사용자가 지정한 클로저를 실행하게 됩니다. 
  • 여기서 bindbindAndFire의 차이는 bind는 value값이 바뀌었을때 실행되지만(오직 클로저를 저장하는 용도), bindAndFire는 함수가 실행될때 마찬가지로 클로저를 저장(bind)하고, 일단 한번 value의 값을 매개변수로 받아 클로저를 실행(Fire)기키게 됩니다.  

처음에는 저 코드를 봐도 이해가 잘 안되실수 있습니다. 인스턴스에 클로저를 담는다는 개념이 저도 이해가 가지않아서 처음에는 포기했고 두번째는 스터디를 같이 하는분의 도움을 받아 이해할수 있었습니다. 
바인드가 사용자가 원하는 방식의 끈을 연결하는 것이라고 생각하시면 이해하기 쉬울것 같습니다 ㅎㅎ

'IOS > iOS' 카테고리의 다른 글

[TIL] iOS의 구조  (0) 2020.11.29
[TIL] iOS. Password AutoFill  (0) 2020.11.26
iOS. 유효성 검사 포맷( Validation Check )  (0) 2020.11.18
[TIL] iOS. Button  (0) 2020.11.14
[TIL] iOS. View  (0) 2020.11.10