Conversation
- 처음 체크박스를 누른 후 데이트피커만 움직이면 저장이 활성화 되는 오류 해결 - 건너뛰기 직후 계획 필터링에 진입했을 때 체크박스가 체크되어 있지 않은 오류 해결
7 tasks
thingineeer
requested changes
Jan 11, 2025
Member
Member
Author
There was a problem hiding this comment.
수정해서 올렸습니다!
2025-01-11.5.00.23.mov
thingineeer
approved these changes
Jan 11, 2025
Member
thingineeer
left a comment
There was a problem hiding this comment.
설명을 야물딱 지게 해서 코드 이해하기는 편했습니다.
코드가 조금 복잡하긴 한데 천천히 리팩하면 좋을 것 같아요!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


🩵 Issue
close #249
💙 변경된 내용
1️⃣번 커밋: 직무 선택 안해도 저장하기 버튼이 활성화되어 있음 -> 항상 하나는 선택되게 수정
저장된 직무 필터값 없을때 마지막 값인
전체가 뜨게했습니다.뷰모델과 뷰컨에서 같은 값 한번 더 누르면 값이 nil이 되는 로직을 제거했습니다.
2️⃣번 커밋: 상단에 필터라는 텍스트 추가
요건 그냥
필터적혀있는 라벨 FilteringViewController 상단에 추가했습니다.3️⃣번 커밋: 계획필터링뷰 UILabel ->LabelFactory로 변경
PlanFilteringViewController에서 LabelFactory말고 UILabel 썼길래 수정했습니다.
4️⃣번 커밋: 계획 필터링 관련 QA 반영
UserFilteringData와 TemporaryFilteringData의
startYear, startMonth에 현재 날짜값 넣어주는 코드 삭제했습니다. -> 초기값이 nil 이 될 수 있도록기존의 PlanFilteringViewController에 있던 아래 코드를 삭제했습니다.
선택된 버튼 값을 뷰모델만 관리하도록 옮겨주었고, 따라서
체크 박스와 선택된 버튼값을 설정해주던 코드들을 함께 삭제했습니다. (아래 코드 삭제)
bindViewModel() 에서 각각의 버튼이나 데이트 피커, 체크 박스가 동작할때 input으로 해당 값을 전달해주었고
output에 따라 UI를 업데이트 해주는 함수를 호출 시켰습니다.
년도와 요일의 경우, 뷰컨트롤러에서 '-'Placeholder를 넣어주는 작업이 필요했어서, .take(1)사용해서 초기값이 설정되는 단 한번만 초기값 년도와 달이 숫자이면 해당 숫자로 세팅 setInitialDate() 아니면 '-'가 추가되도록 하였습니다.
이전 코드와 달리 isCheckBoxChecked와 isFilterApplied(저장하기 버튼 활성화 관련)를 분리하여 관리하였습니다.
let output = viewModel.transform(input: input, disposeBag: disposeBag) Observable.combineLatest(output.selectedYear.asObservable(), output.selectedMonth.asObservable()) .take(1) .subscribe(onNext: { [weak self] year, month in guard let self = self else { return } if let year = year, let month = month, year > 0, month > 0 { self.customPickerView.setInitialDate(year: year, month: month) } else { self.customPickerView.addPlaceholder() } }) .disposed(by: disposeBag) output.selectedGrade .drive(onNext: { [weak self] grade in guard let self = self else { return } if let grade = grade { self.updateButtonState(for: self.gradeButtons, selectedValue: grade.displayName) } else { self.updateButtonState(for: self.gradeButtons, selectedValue: nil) } }) .disposed(by: disposeBag) output.selectedPeriod .drive(onNext: { [weak self] period in guard let self = self else { return } if let period = period { self.updateButtonState(for: self.periodButtons, selectedValue: period.displayName) } else { self.updateButtonState(for: self.periodButtons, selectedValue: nil) } }) .disposed(by: disposeBag) output.isCheckBoxChecked .drive(onNext: { [weak self] isChecked in self?.checkBox.setChecked(isChecked) }) .disposed(by: disposeBag) output.isFilterApplied .drive(filteringState) .disposed(by: disposeBag) }Output에서 isFilterApplied를 추가하여 체크 박스와 별개로 상태를 관리하였습니다. 이전 코드에서는 저장하기 상태만 관리하고, 체크 박스 상태를 뷰컨에서 관리를 하였습니다.
Properties에서는 hasNonNilValueRelay와 isCheckBoxRelay가 추가되었습니다.(아래 설명 계속)
체크박스에 input이 들어올 경우, 체크박스가 true 인경우 나머지 계획 필터링 값을 모두 nil을 해주었고,
hasNonNilValueRelay를 false로 해주었습니다.
hasNonNilValueRelay를 한 이유는,
체크 박스를 클릭한 후 계획 필터링 값이 하나라도 nil이 아니게 될때 체크 박스를 false로 바꾸기 위해 아래와 같은 리턴값을 체크박스 아웃풋 값으로 반환하도록 했었는데,
이럴 경우
ex) 체크 박스를 누른 . 학년 버튼을 1학년을 눌렀다가 다시 취소한 경우 다시 체크 박스가 자동 활성화 되는 문제가 있었습니다.
따라서 위와 같은 느낌으로 hasNonNilValueRelay를 통해 사용자가 체크 박스를 누르지 않았는데 모두 Nil값이라 자동 체크박스가 체크되는 것을 방지하였습니다.
2025-01-11.7.25.34.mov
combinedRelays의 경우 체크박스 상태 결정에도 쓰이고, 저장하기 버튼 상태 결정에도 쓰여서 하나로 빼서 사용했습니다.
isCheckBoxChecked의 경우
isFilterApplied의 경우 isCheckBoxChecked와 combinedRelays(=계획 필터링 값들)을 통해 체크 박스가 true 상태이면 항상 저장하기 버튼 활성화, 체크 박스가 false일 경우, 모든 계획 필터링 값이 nil이 아닐때만 저장하기 버튼이 활성화 되도록 하였습니다.
5️⃣번 커밋: [직무 카테고리] 섹션과 [계획] 섹션 간의 간격 수정
기본 UISegmentedControl은 기본적으로 모든 세그먼트의 너비를 균등하게 나누기 때문에,
텍스트의 위치 및 세그먼트 너비가 동일하게 고정되어 세부적인 조정이 불가능했습니다.
텍스트 색상은 UIColor.clear로 설정해 기본 텍스트는 보이지 않게 하고 사용자 정의한 배경 뷰에 텍스트를 추가했습니다.
보이지 않는데 아래 코드가 남아있는 이유는 CustomSegmentedControl의 크기를 기본 텍스트와 스타일 기반으로 계산하고, 이후 커스터마이징된 UI (ex 아래 추가한 backgroundView 등)에서 이를 활용하기 위해 setTitleTextAttributes를 설정했습니다.
세그먼트의 너비안에서 테스트와의 여백도 조절할 수 없었습니다.
setContentPositionAdjustment(_:forSegmentType:barMetrics:)를 사용해서 억지로 조절할 순 있었으나,많은 시도를 해보았으나 CustomSegmentedControl로 만들기에는 조절해주는 간격을 규격화 시킬 수가 없었습니다!
따라서 아래와 같은 방법을 사용했습니다.
frameForSegment 함수를 통해 각 세그먼트의 텍스트 크기와 간격을 기준으로 정확한 CGRect를 만들어주었습니다.
addBackgroundView를 통해 기존의 세그먼트 텍스트의 경우 기존의 세그먼트 텍스트 대신 배경 뷰와 레이블을 추가하여 텍스트를 렌더링되도록 하였습니다.
백그라운드를 추가해도, 터치 영역은 UISegmentedControl이 자동으로 계산해놓은 값 그대로 였기 때문에 터치 영역도 아래와 같이 텍스트 크기 기반으로 크기를 계산하여 설정해주었습니다.
터치 시 selectedSegmentIndex를 즉시 업데이트하고 valueChanged 이벤트를 트리거 해줍니다.
추가해준 백그라운드 안의 라벨들은 해당 세그먼트가 선택될때 아래 방식으로 텍스트 색깔이 바뀔 수 있도록 하였습니다.
6️⃣번 커밋: 초록색 바가 따라오는 속도 수정
underbar.layer.removeAllAnimations()을 추가하여 이전에 실행중인 애니메이션이 있으면 강제로 중단하도록 하였습니다.
애니메이션 시간을 0.27 -> 0.17로 줄였는데,
안드가 어떻게 구현을 했는지 몰라서, 초록바 따라오는 속도가 느리다는게 애니메이션을 아예 없애라는 것일까요?? 바로 바로 밑에 뜨게? 일단 시간 줄여서 구현해놓았습니다!
📘 ScreenShot
2025-01-11.4.03.03.mov