티스토리 뷰

iOS

MVVM패턴

홍복치 2020. 4. 2. 19:17

https://usinuniverse.bitbucket.io/blog/rxswiftmvvmpart1.html 를 개인적으로 정리한 글입니다.

MVVM

- Model, View, View Model의 약자

 

 

View

- View와 애니메이션

 

 

ViewModel

- 비즈니스 로직과 API 호출

- Model과 상호작용하여 View에서 필요한 데이터를 가지고 있지만, 직접 건네주는 것이 아님

-> View에서 바인딩을 통해 ViewModel에게서 필요한 데이터를 가져가야 함

- View Model은 View에 대해 아무것도 몰라야 하며 UIKit을 import해서도 안됨

 

 

 

RxSwift

- View와 ViewModel을 바인딩하기 위한 효과적 도구

- Reactive Programming에 기반을 두고 있음

 

 

Reactive Programming이란

 

(1) 기존의 프로그래밍

var a = 3
var b = 7
var c = a+b // 10
a = 1
print(c) //10

 

(2) Reactive Programming

var a = 3
var b = 7
var c = a+b // 10
a = 1
print(c) //8

값이 변경된 a에 대해 자동으로 c가 변경된 것을 볼 수 있음

-> 변화에 반응하여 자동으로 변경된다는 것이 Reactive Programming의 핵심

 

Reactive Programming에서는 모든것이 스트림이며 UI이벤트나 네트워크 요청도 역시 스트림

 

스트림이란? 

- 버튼을 누르면 특정 문자열을 출력하는 함수가 있다는 함수가 있다고 가정

- 버튼을 누르는 순간부터, 출력을 완료하는 과정 자체가 하나의 스트림

 

 실생활의 예시

- 우리는 항상 휴대폰(Observable : 관찰가능한) 을 예의주시하고 있음

- 전화가 오는지, 카톡이 오는지 항상 신경씀  : SubScribe(구독하다)

 -> 우리는 필요에 따라 관찰가능한 휴대폰을 구독하고 있다가 휴대폰이 방출하는 이벤트에 반응

 

 

RxSwift의 기초

 

Observable과 Subscriber

- Observable과 Observers(혹은 Subscribers)가 존재

- ObservableType protocol을 준수한다면 어떤 것도 Observable이 될 수 있음

 

(1) Observable 생성

let observableString = Observable.just("Hello, RxSwift")
let observableInt = Observable.of(0,1,2)
let observableDict = Observable.from([1: "Hello", 2:"RxSwift"])

- just, of, from 등은 Observable 생성 연산자

 

(2) Observable 구독

let observableString = Observable.just("Hello, RxSwift")
observableString.subscribe{ print($0) }
//next(Hello, Rxswift)
//completed

- 왜 그냥 "Hello, RxSwift" 출력이 아니라 next, completed가 붙을까?

-> Rx세계에서는 모든것이 스트림이기 때문

 

 

 

※ Marble Diagram

 

- 3개의 Observable 

첫 번째 Observable : 1부터 6까지의 int형의 데이터가 6번 방출된 후 종료

두 번째 Observable : String형의 값인 a~f까지 방출하다 에러

세 번째 Observable : 세번의 tap 이벤트 발생

 

- 해석

가로선 : 시간의 흐름, 하나의 스트림

| : 하나의 스트림 종료 시점

X : 에러를 나타냄, 스트림 종료 시점

 

 

(3) next, completed, error

Rx 하에서는 스트림이 next, completed, error 3가지 종류의 이벤트로 구성

- Observable이 구독자에게 방출할 값이 있다면 next 이벤트를 통해 방출 

-> 더 이상 방출할 값이 없다면 마지막으로 completed 이벤트 방출 후 종료

-> 중간에 error가 발생한다면 error 이벤트를 방출 후 종료

var observableInt = Observable.of(1,2,3,4,5,6)
observableInt.subscribe{ print($0) }
//next(1)
//next(2)
//next(3)
//next(4)
//next(5)
//next(6)
//completed

 

(4) Dispose : Observable 구독 취소

Observable을 구독할 수 있듯 구독을 취소할 수도 있음

이것을 Dispose라 부르며, Rx에서는 DisposeBag에 담아 구독 취소

-> 순환참조로 인한 메모리 누수를 피하기 위함

let disposeBag = DisposeBag()

var observableInt = Observable.of(1,2,3,4,5,6)
observableInt.
          subscribe { print($0) }
              .disposed(by: disposedBag)

- ViewController에서 메모리가 해제될 때 disposeBag에 담긴 메모리에서 같이 해제

- 만약 중간에 해제하길 원한다면 disposeBag을 초기화하면 됨

 

 

※ RxSwift 코드 예제

Int형을 방출하는 Observable을 구독하고 있다가 2의 배수인 경우에만 10을 곱해서 출력하는 예제코드

let disposeBag = DisposeBag()

var observableInt = Observable.of(1,2,3,4,5,6,7,8)
observableInt
     .filter { $0.isMultiple(of:2) } //2의 배수만 filter
     .map { $0 * 10 } //10 곱하기
     .subscribe { print($0) } //방출되는 값들이 출력
     .disposed(by: disposeBag) //모든 값이 방출되면 구독을 취소
  
  //next(20)
  //next(40)
  //next(60)
  //next(80)
  //completed

 

 

최근에 올라온 글
Total
Today
Yesterday