RxSwift๋ฅผ ํ์ฉํด View - ViewModel์ ๋ฐ์ธ๋ฉํ๋ ๊ณผ์ ์์ View์ ๋ค์ํ Input๋ค์ ์กฐํฉ / ๋ณํํ์ฌ ์ฌ์ฉํ๊ฒ ๋๋ค. ์ฌ๊ธฐ์ Observable์ ์ฌ๋ฌ๋ฒ ๊ตฌ๋ ์ํค๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ, ์ฝ๋ ์์ฑ ์ ์ง์ ๊ฒช์๋ ๋ฌธ์ ๋ฅผ ํตํด ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ์ ์ ๋ํด ์ดํด๋ณด๊ณ ์ฃผ์์ฌํญ์ ๊ธฐ๋กํ๊ณ ์ ํ๋ค.
๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ์ฝ๋
// ViewModel
struct Input {
let title: Driver<String>
let date: Driver<Date>
let body: Driver<String>
let rightBarButtonTapped: Driver<Void>
let leftBarButtonTapped: Driver<Void>
}
struct Output {
let canSave: Driver<Bool>
let save: Observable<Void>
let canEdit: Driver<Bool>
let dismiss: Driver<Void>
}
func transform(_ input: Input) -> Output {
let projectContents = Driver.combineLatest(input.title,
input.date,
input.body)
let canSave = projectContents
.map { title, _, body in
return title != "" || body != ""
}
.asDriver(onErrorJustReturn: false)
// ๋ฌธ์ ๊ฐ ๋ฐ์ํ Observable
let save = input.rightBarButtonTapped
.asObservable()
.withLatestFrom(projectContents)
.map { title, date, body in
return Contents(title: title,
date: date,
body: body,
id: UUID())
}
.map { [unowned self] project in
try useCase.create(project: project)
delegate?.projectCreated()
}
let canEdit = Driver.just(true)
let dismiss = Driver.merge(input.leftBarButtonTapped,
projectSave.asDriver(onErrorJustReturn: ()))
.do(onNext: navigator.toMain)
return Output(canSave: canSave,
save: projectSave,
canEdit: canEdit,
dismiss: dismiss)
}
ViewModel์ Input์ ์ฐจ๋ก๋ก ์ค๋ช ํ๋ฉด ์๋์ ๊ฐ๋ค.
์ ์ฝ๋์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๋ถ๋ถ์ save ์ด๋ค.
save๋ ์ค๋ฅธ์ชฝ ๋ค๋น๊ฒ์ด์
๋ฐ ๋ฒํผ์ tap ์ด๋ฒคํธ๋ฅผ ํธ๋ฆฌ๊ฑฐ๋ก ํ์ฌ view์์ ๋ฐ์์จ Input์ useCase๋ฅผ ํตํด DB์ ์ ์ฅํ๋ ์คํธ๋ฆผ์ด๋ค.
dismiss ์ ๊ฒฝ์ฐ ์ผ์ชฝ, ์ค๋ฅธ์ชฝ ๋ค๋น๊ฒ์ด์
๋ฐ ๋ฒํผ์ tap ์ด๋ฒคํธ๋ฅผ mergeํ์ฌ ํ๋ฉด์ dismissํ๋ ์คํธ๋ฆผ์ด๋ค.
๋ ์คํธ๋ฆผ์ ๋ชจ๋ Output์ผ๋ก ๋ฐํ๋์ด ViewController์์ ๊ตฌ๋ ์ด ์ผ์ด๋๋ค.
๐ย ๋ฌธ์ ์
save ์คํธ๋ฆผ์ด 2ํ ์คํ๋๋ค.