회원 가입할 때 필수 조건에 대해서 모두 체크했을 경우에 버튼의 활성/비활성, 혹은 전체 버튼 선택에 대한 로직을 구현하는데 있어서 생각보다 까다로워서 공유합니다~!
더 좋은 로직, 혹은 좋은 의견 있으시면 댓글 부탁드려요!
일단 어떤 버튼을 눌렀는지 버튼 타입에 대해서 만들었습니다.
enum AgreementButtonType {
case allAgree // 전체 동의
case requiredFirst // 필수 동의 첫번째
case requiredSecond // 필수 동의 두번째
case requiredThird // 필수 동의 세번째
case notRequiredFourth // 선택 사항(마케팅 동의 같은)
}
그래서 버튼을 눌렀을 때 해당 버튼 타입으로 변환해서 Input으로 가져왔습니다~!
// View
Observable<AgreementButtonType>.merge([
selectAllAgreement.rx.tap.map { _ in .allAgree },
firstAgreement.rx.tap.map { _ in .requiredFirst },
secondAgreement.rx.tap.map { _ in .requiredSecond },
thirdAgreement.rx.tap.map { _ in .requiredThird },
fourthAgreement.rx.tap.map { _ in .notRequiredFourth }
])
.bind(to: viewModel.input.buttonTapped)
.disposed(by: disposeBag)
// ViewModel
struct Input {
let buttonTapped = PublishRelay<AgreementButtonType>()
}
그 다음 각 버튼의 IsSelected 상태에 대한 BehaviorRelay로 만들어놓고 스트림을 연결했습니다. 그리고 Input으로 들어오는 버튼 타입에 대한 switch문으로 분기처리를 했어요.
let allAgreeIsSelected = BehaviorRelay<Bool>(value: false)
let requiredFirstIsSelected = BehaviorRelay<Bool>(value: false)
let requiredSecondIsSelected = BehaviorRelay<Bool>(value: false)
let requiredThirdIsSelected = BehaviorRelay<Bool>(value: false)
let notRequiredFourthIsSelected = BehaviorRelay<Bool>(value: false)
input.buttonTapped
.bind { type in
switch type {
case .allAgree:
let preValue = allAgreeIsSelected.value
[allAgreeIsSelected,
requiredFirstIsSelected,
requiredSecondIsSelected,
requiredThirdIsSelected,
notRequiredFourthIsSelected]
.forEach { $0.accept(!preValue) }
case .requiredFirst:
requiredFirstIsSelected.accept(!requiredFirstIsSelected.value)
case .requiredSecond:
requiredSecondIsSelected.accept(!requiredSecondIsSelected.value)
case .requiredThird:
requiredThirdIsSelected.accept(!requiredThirdIsSelected.value)
case .notRequiredFourth:
notRequiredFourthIsSelected.accept(!notRequiredFourthIsSelected.value)
}
}
.disposed(by: disposeBag)
버튼들을 모두 선택했을 경우에 전체 버튼의 선택과 해제, 그리고 필수 버튼들을 모두 선택했을 때 다음으로 넘어가는 버튼의 활성화는 모두 combineLatest로 구현했습니다.
Observable.combineLatest(
requiredFirstIsSelected,
requiredSecondIsSelected,
requiredThirdIsSelected,
notRequiredFourthIsSelected)
{ $0 && $1 && $2 && $3 }
.bind(to: allAgreeIsSelected)
.disposed(by: disposeBag)
let nextButtonIsEnable = Observable.combineLatest(
requiredFirstIsSelected,
requiredSecondIsSelected,
requiredThirdIsSelected)
{ $0 && $1 && $2 }