PLUB 개발회고 (4)

이건준·2023년 2월 17일
0

1. subscribe(with:)

  • 우리가 보통 rx를 사용할때 다양한 오퍼레이터로 이어준 스트림을 방출하고자할때 각각의 종류에 따라 subscribe, drive, emit 등등을 사용하게 된다

  • 방출된 값에 따른 프로퍼티를 사용하고자할때 우리는 주로 2가지의 방법을 사용하게 된다

  1. guard let self = self~
  2. withUnretained(obj)
  • 나는 위 방법중에서 2번을 주로 사용하였는데 subscribe(with:), drive(with:)와 같이 하나의 오퍼레이터로 단축시킬 수 있었다

  • 또한 2번 방법을 사용할때에 Driver에는 withUnretained를 사용할 수 없어서 asObservable로 변환 이후 사용했었는데 아주 유용한 오퍼레이터같다

2. didScroll vs didEndDragging

  • 보통 서버를 이용해서 어떤 데이터를 내려보내야할때 파라미터로 page값을 받아서 한번에 받아오는 양을 조절하게 된다

  • 프론트딴에서 이러한 페이징처리를 할때 스크롤뷰의 delegate를 이용하게 되는데 이때 가장 많이 사용되는 코드가 다음과 같다

homeCollectionView.rx.didScroll
      .subscribe(with: self, onNext: { owner, _ in
        let offSetY = owner.homeCollectionView.contentOffset.y
        let contentHeight = owner.homeCollectionView.contentSize.height
        
        if offSetY > (contentHeight - owner.homeCollectionView.frame.size.height) {
          owner.viewModel.fetchMoreDatas.onNext(())
        }
      })
      .disposed(by: disposeBag)
  • 헌데 딱 이 코드만을 가지고 viewModel에 데이터를 요청하게되면 문제가 생긴다

  • 그건 바로 끝까지 스크롤시에 offSetY값이 해당 조건문에 계속 걸려 무한정으로 fetchMoreDatas를 호출하게되는 문제점이다

첫번째 해결법

  • didScroll대신에 didEndDragging을 이용하는 것이였다

  • 위 코드에서 didScroll -> didEndDragging으로만 변경하면 스크롤하고 한번 떼었을때의 offsetY값만을 판단하여 내가 원하는 딱 한번 데이터를 요청하게 된다

-> 하지만 위 같은 방법엔 문제가 있다. 바로바로 스크롤하여 데이터를 요청하고싶은 클라이언트의 사용에 문제가 발생한다

-> 즉 didScroll을 통해서 바로바로 데이터를 요청해야하는건 맞지만 viewModel내부에서 특정 조건을 걸어줘야만 무한정 요청하는 부분을 막을 수 있다는 생각이 들었다

두번째 해결법

  • 그것은 바로 해당 페이지가 마지막 페이지인지에 대한 여부, 데이터를 요청하는 간격동안은 요청을 받지않는것이다
let inquireRecommendationMeeting = currentPage
      .flatMapLatest { page in
        if try !isLastPage.value() && !isLoading.value() { // 마지막 페이지가 아니고 로딩중이 아닐때
          isLoading.onNext(true)
          return MeetingService.shared.inquireRecommendationMeeting(page: page)
        }
        return .empty()
      }
  • 위 코드처럼 마지막페이지인지 로딩중인지에 대한 여부를 확인하여 서버에 데이터를 요청하게끔하였고 해당 문제를 해결하였다

개선점

  • 위와 같은 코드는 페이징에 따른 데이터요청에 대한 문제점은 해결해주었다, 하지만 사용하다보니 문제가 발생하였다
  1. 필터 혹은 분류타입 혹은 검색에 따른 요청을 할때 단 한번이라도 isLastPage값이 true로 변경되어지게되면 다시는 false로 변경되어지지않는 문제가 발생하였다
let requestSearch = Observable.combineLatest(searchKeyword, currentPage, searchFilterType, searchSortType)
      .do(onNext: { _ in
        isLastPage.onNext(false)
        currentPage.onNext(1)
      })
      .flatMapLatest { (keyword, page, filterType, sortType) in
        if try !isLastPage.value() && !isLoading.value() { // 마지막 페이지가 아니고 로딩중이 아닐때
          isLoading.onNext(true)
          return RecruitmentService.shared.searchRecruitment(searchParameter: .init(keyword: keyword, page: page, type: filterType.text, sort: sortType.text))
        }
        return .empty()
      }
  • 위 코드에서처럼 요청하기이전 do오퍼레이터를 이용하여 상태값들을 초기화시켜주는 작업을 추가해주었고 해당 문제를 해결하였다

3. leading trailing vs directionalHorizontal

  • 스냅킷을 이용하여 오토레이아웃을 주로 작성하는데 좌우에 대한 컨트롤을 할때 leading trailing값을 사용한다

  • leading trailing을 이용할 수도 있지만 directionalHorizontal을 이용하면 코드를 단축시킬 수 있다

interestListCollectionView.snp.makeConstraints {
      $0.top.equalTo(headerView.snp.bottom)
      $0.directionalHorizontalEdges.bottom.equalToSuperview()
    }

edges vs directionalEdges

homeCollectionView.snp.makeConstraints {
      $0.edges.equalToSuperview().inset(16)
    }
  • 항상 해당 UI를 슈퍼뷰에 상하좌우 붙이고싶을때 위와 같은 코드를 많이 사용하였다

  • 하지만 edges를 뜯어보면 top, left, right, bottom을 의미한다

즉 edges는 Localized를 위한 leading trailing을 사용하지않는다

  • directionalEdges는 top, leading, trailing, bottom을 의미한다

4. 정수 / 정수 vs 실수 / 실수

  • 나는 항상 셀에 대한 크기가 고정적이지않고 데이터갯수에 따라 바껴야한다던지 핸드폰 사이즈는 천차만별이기에 특히나 너비같은 경우는 값을 잘 지정해주어야한다
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    switch selectedCategoryType {
    case .chart:
      return CGSize(width: collectionView.frame.width, height: collectionView.frame.height / 4 - 6)
    case .grid:
      return CGSize(width: collectionView.frame.width / 2 - 6, height: collectionView.frame.height / 2.5)
    }
  }
  • 위와 같은 코드는 아마 많은 분들이 사용해보셨을 코드일 것이다

  • 하지만 이처럼 간단한 경우가 아닌 복잡한 경우에는 이야기가 달라진다

  • 정수 / 정수 일때 몫이 나온다는 사실을 알고있었을 것이다

그렇다면 몫과 나머지를 한번에 보고싶을때 정확한 값을 구하고싶을때는 어떻게 해야할까 ??

  • 위와 같은 상황일 경우에 실수 / 실수를 이용해줄 수 있다
$0.height.equalTo(ceil(Double(model.count) / Double(4)) * (48 + 4 + 21) + (ceil(Double(model.count) / Double(4)) - 1) * 16 + Double(24 + 24))
  • 만약에 위와 같은 경우에 정수/정수로 했다면 내가 원하는 높이보다 살짝 적은 결과값이 나왔는데 실수/실수로 변경함으로써 내가 원하는 높이의 결과값을 얻을 수 있었다

0개의 댓글