Taehyeon-Kim / SeSAC

☀️ SeSAC Daily Reporting
27 stars 0 forks source link

[221101] TIL #146

Open Taehyeon-Kim opened 1 year ago

Taehyeon-Kim commented 1 year ago

MVVM Input/Output Modeling

데이터에 대한 처리의 흐름을 분리해놓는 작업 데이터가 흘러가는 방향에 집중

데이터의 흐름을 명확하게 구분해서 볼 수 있다는 장점이 있다.

output.stepButtonDidTap
    .bind { _ in
        print("SHOW ALERT")
    }
    .disposed(by: disposeBag)

코드 구조

ViewModel

struct ValidationViewModel {

    struct Input {
        let text: ControlProperty<String?>
        let stepButtonDidTap: ControlEvent<Void>
    }

    struct Output {
        let validText: Driver<String>
        let validation: Observable<Bool>
        let stepButtonDidTap: ControlEvent<Void>
    }

    func transform(input: Input) -> Output {
        let validText = BehaviorRelay(value: "닉네임은 최소 8자 이상 필요해요").asDriver()

        // 데이터스트림을 바꿔가는 작업도 ViewModel로 숨겨놓음
        let validation = input.text
            .orEmpty
            .map { $0.count >= 8 }
            .share()

        return Output(
            validText: validText,
            validation: validation,
            stepButtonDidTap: input.stepButtonDidTap
        )
    }
}

ViewController + Bind

private func bind() {
    let input = ValidationViewModel.Input(
        text: nameTextField.rx.text,
        stepButtonDidTap: stepButton.rx.tap)
    let output = viewModel.transform(input: input)

    output.stepButtonDidTap
        .bind { _ in
            print("SHOW ALERT")
        }
        .disposed(by: disposeBag)

    output.validText
        .asDriver()
        .drive(validationLabel.rx.text)
        .disposed(by: disposeBag)

    output.validation
        .bind(to: stepButton.rx.isEnabled, validationLabel.rx.isHidden)
        .disposed(by: disposeBag)

    output.validation
        .withUnretained(self)
        .bind { vc, value in
            vc.stepButton.backgroundColor = value ? .systemPink : .lightGray
        }
        .disposed(by: disposeBag)
}
Taehyeon-Kim commented 1 year ago