input/output 설정
struct Input {
let didIdTextFieldChange: Observable<String> //id 텍스트필드 string
let didPasswordTextFieldChange: Observable<String> //pwd 텍스트필드 string
let didPasswordCheckTextFieldChange: Observable<String> //pwd 체크 텍스트필드 string
let didPasswordTextFieldDidTapEvent: Observable<Void> //pwd 체크 텍스트필드 viewEditing
let tapConfirmButton: Observable<Void> // 회원가입 버튼 선택
// let tapBackButton: Signal<Void>
}
struct Output {
// let didBackButtonTapped: Signal<Void>
// let didConfirmButtonTapped: Signal<Void>
let isIdValid = PublishRelay<Bool>() // id Valid bool 값
let isPasswordValid = PublishRelay<Bool>() // Password bool 값
let isPasswordCheckValid = PublishRelay<Bool>() // PasswordCheck bool 값
let isAllInputValid = PublishRelay<Bool>() // 회원가입 버튼 isEnable bool 값
}

Input → Output으로 바꾸는 로직
- 아이디
- didIdTextFieldChange를 8자리 이상 인지 확인 (Bool 값)
- isIdValid에 Bool 값 accept
- 패스워드
- didPasswordTextFieldChange를 8자리 이상, 숫자/영문, 특수문자 확인 (Bool 값)
- isPasswordValid에 Bool 값 accept
- 패스워드 확인
- didPasswordCheckTextFieldChange가 didPasswordTextFieldChange와 값이 동일한지 확인 (Bool 값)
- didPasswordCheckTextFieldChange가 isEmpty 한지 확인 ( isEmpty를 확인하지 않는다면 그냥 비워져 있어도 false 값을 방출)
- isPasswordCheckValid에 Bool 값 accept
- 가입 버튼
- isIdValid, isPasswordValid, isPasswordCheckValid가 모두 true인지 확인
viewModel - 아이디
func transform(input: Input) -> Output {
let output = Output()
input.didIdTextFieldChange // Observable<String>
.distinctUntilChanged()
.withUnretained(self)
.map { owner, text in
self.validate(text: text)
}
.subscribe(onNext: { result in
output.isIdValid.accept(result)
})
.disposed(by: disposeBag)
}
private func validate(text: String) -> Bool {
return text.count > 8
}
didIdTextFieldChange
를 map
을 활용해서 validate
체크 후 bool으로 변환
subscribe
에서 output.isIdValid
에 bool값을 accept 한다.
validate
에 적합하지 않다면 false를 방출, 적합하다면 true를 방출한다.
viewModel - 패스워드
input.didPasswordTextFieldChange // Observable<String>
.distinctUntilChanged()
.withUnretained(self)
.map { owner, text in
owner.passwordValidCheck(password: text)
}
.subscribe(onNext: { result in
output.isPasswordValid.accept(result)
})
.disposed(by: disposeBag)
private func passwordValidCheck(password: String) -> Bool {
let passwordRegex = "^(?=.*[A-Za-z])(?=.*\\\\d)(?=.*[@#$%^&+=]).{8,20}$"
let passwordPredicate = NSPredicate(format: "SELF MATCHES %@", passwordRegex)
return passwordPredicate.evaluate(with: password)
}
- 아이디와 동일하다.
didPasswordTextFieldChange
를 map
을 활용해서 validate
체크 후 bool으로 변환
subscribe
에서 output.isPasswordValid
에 bool값을 accept 한다.
viewModel - 패스워드 확인
input.didPasswordTextFieldDidTapEvent // Observable<Void>
.withLatestFrom(Observable.combineLatest(input.didPasswordTextFieldChange, input.didPasswordCheckTextFieldChange))
.map { password, checkPassword in
!checkPassword.isEmpty && password == checkPassword
}
.subscribe(onNext: { result in
output.isPasswordCheckValid.accept(result)
})
.disposed(by: disposeBag)
didPasswordTextFieldDidTapEvent
은 pwd 체크 텍스트필드의 viewEditing을 담당하는 input Observable이다.