[MVVM] 0. MVVM과 데이터바인딩

miori·2022년 6월 2일
0

ios-MVVM

목록 보기
1/6

mvvm 부시기 🫡

앞서, RxSwift + MVVM 리팩토링 를 통해 MVVM 패턴을 알아본 적이 있다.
하지만 RxSwift를 사용하지 않고, MVVM을 적용해보고 싶었다.

여기서 생기는 의문점은, 그럼 RxSwift에서 사용했던 바인드의 역할을 어떻게 처리해줄까였다.
열심히 구글링도 해보고, 깃허브도 참고해본 결과, 이에 대한 해결책이 나와있었고, 이번에 그 부분에 대해 정리해보는 시간을 가지려고 한다.

didSet 활용

위의 그림처럼 업데이트가 되었을때 업데이트가 되었다고 알려줄 수 있는 무언가가 필요하다.
또한 업데이트가 될때마다 수정이 될 필요가 있다.

swift 에서 제공해주는 property observer 인 didset매서드를 활용해준다면 이 부분을 해결해 줄 수 있다.

- 예시 코드

didSet이 무엇인가에 대해 알기위해, 간단한 코드를 작성해보았다.
이 코드는 데드리프트 1rm 무게가 변경될때마다 알려주는 코드이다.

struct My1RM {
    
    // property observer
    var currentDeadLiftWeight: Double = 70 {
			
        willSet {
            print("\(currentDeadLiftWeight)kg에서 \(newValue)kg으로 가나요??")
        }
        
        didSet {
            print("\(oldValue)kg에서 \(currentDeadLiftWeight)kg으로 올랐다 🔥")
        }
    }
}

var my1RM : My1RM = My1RM()

my1RM.currentDeadLiftWeight = 80

이 코드의 결과물은 다음과 같다.

70.0kg에서 80.0kg으로 가나요??
70.0kg에서 80.0kg으로 올랐다 🔥

커스텀 Observable 헬퍼클래스 만들기

이제, didSet의 역할을 알아보았으니, 이번 글의 주 목적인 헬퍼클래스를 만들어보도록 하겠다.

- 1. value 생성

class Observable<T> {
    var value : T {
        didSet {
            
        }
    }
    
    init(_ value : T) {
        self.value = value
    }
}

우선 유연함과 재사용성을 높이기위해. 제네릭 타입으로 선언을 해줄 수 있다.

- 2. 클로저 작성

didSet 매서드를 통해 value 값이 변경될때 마다, value값을 받아, 일어날 일에 대해 작성을 해야한다.
이를 해결해 줄 수 있는 놈은 "클로저" 일거 같다.
private var listener: ((T) -> Void)? 코드를 추가해보겠다.

class Observable<T> {

	private var listener: ((T) -> Void)?
    
    var value : T {
        didSet {
            self.listener?(value)
        }
    }
    
    init(_ value : T) {
        self.value = value
    }
}

지금까지의 코드를 본다면, value 값이 변경이 되었을 때 그 값을 받아와 어떤한 일을 수행할 것이다.

그럼, value에 저장했던 값을 전달해주고, 전달받은 클로저를 listener에 전달해주려면 어떻게 해야할까?

-3. bind 함수 작성

func bind(_ closure: @escaping (T) -> Void) {
    closure(value)
    self.listener = closure
}

위와 같이 작성해 줄 수 있다.

-4. 전체코드

class Observable<T> {

    private var listener: ((T) -> Void)?
    
    var value: T {
        didSet {
            self.listener?(value)
        }
    }    

    init(_ value: T) {
        self.value = value
    }
    
    func bind(_ closure: @escaping (T) -> Void) {
        closure(value)
        self.listener = closure
    }
}

새로운 기술을 배우는 것은 흥미롭고, 올바르게 잘 적용한다면 개발실력도 향상이 된다고 생각한다. 하지만 기본이 탄탄하다는 전제가 필수조건이다. 그래서 이번에 MVVM 자체를 가지고 공부를 시작하는 이유이다.

이번학습을 통해, swift의 강력한 기능중 하나인 제네릭을 다시 복기할수 있었다.


다음번엔, 이를 활용해서 실제 적용해보는 실습을 정리해보겠다 :)

reference :

profile
iS를 공부하는 miori 입니다.

0개의 댓글