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 값
    }

Simulator Screen Shot - iPhone 13 mini - 2023-06-13 at 17.55.36.png

Input → Output으로 바꾸는 로직

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
    }

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)
    }

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)