[221101] TIL
Taehyeon-Kim opened this issue · 1 comments
Taehyeon-Kim commented
MVVM Input/Output Modeling
데이터에 대한 처리의 흐름을 분리해놓는 작업
데이터가 흘러가는 방향에 집중
- VC -> VM
- VM -> VC
데이터의 흐름을 명확하게 구분해서 볼 수 있다는 장점이 있다.
output.stepButtonDidTap
.bind { _ in
print("SHOW ALERT")
}
.disposed(by: disposeBag)
- button tap을 굳이 숨길 필요가 있냐라는 생각이 들 수 있지만, 서버 통신이나 DB 접근 등의 비즈니스 로직을 추가로 처리할 수 있기 때문에 이를 ViewModel 내에 숨겨서 연산을 진행한다. 중요한 것은 output을 구독해서 사용한다는 사실이다.
코드 구조
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)
}