[iOS 11주차] Project PokeDex: indexPathsForVisibleItems 이용하기

DoyleHWorks·5일 전
3

https://github.com/DoyleHWorks/PokeDex

문제 배경

스크롤을 통해 포켓몬 목록을 탐색할 수 있는 앱에서, 보여지고 있는 포켓몬 중, 가장 위에 있는 포켓몬의 번호를 알 수 있도록 하는 기능을 구현했다. 그런데 No.1024~에서 No.10002~로 넘어가게 되는 문제가 발생했다.

문제 파악

기존의 코드는 다음과 같다:

private func updateTopPokemonLabel() {
    guard let firstVisibleIndexPath = collectionView.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row }).first else {
       topPokemonLabel.text = "No.1~"
       return
    }

    let pokemon = viewModel.pokemonItems.value[firstVisibleIndexPath.row]
    if let id = pokemon.id {
        topPokemonLabel.text = "No.\(id)~"
    } else {
        topPokemonLabel.text = "No.Unknown~"
    }
}

문제 접근

문제 접근 1

가설 설정

  1. indexPathsForVisibleItems이 제대로 반환되지 않음
  2. ViewModel과의 데이터 동기화가 잘못됨
private func updateTopPokemonLabel() {
    guard let firstVisibleIndexPath = getFirstVisibleIndexPath() else {
        topPokemonLabel.text = "No.1~"
        return
    }

    // ViewModel 데이터 동기화 확인
    guard firstVisibleIndexPath.row < viewModel.pokemonItems.value.count else {
        topPokemonLabel.text = "No. ~"
        return
    }

    let pokemon = viewModel.pokemonItems.value[firstVisibleIndexPath.row]
    if let id = pokemon.id {
        topPokemonLabel.text = "No.\(id)~"
    } else {
        topPokemonLabel.text = "No.Unknown~"
    }
}

// 더 정확하게 IndexPath를 추출
private func getFirstVisibleIndexPath() -> IndexPath? {
    guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return nil }
    let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size)
    let visibleAttributes = layout.layoutAttributesForElements(in: visibleRect)
    return visibleAttributes?.sorted(by: { $0.frame.origin.y < $1.frame.origin.y }).first?.indexPath
}

해결되지 않음

문제 접근 2

ID를 직접 추출했음해도 똑같은 현상이 발생하는 것으로 보아, 애초에 API로부터 가져올 수 있는 Pokemon ID에 10001부터 시작하는 인덱스가 함께 존재함을 추측하게 됨. 확인해보니 실제로 그러함.

문제 해결

문제가 아닌 기존 사양임을 파악하였음.
사실 ID가 10001부터 시작하는 경우는 처음부터 생각했었는데 그 가능성을 얕보고 문제를 해결하려고 한 느낌이 없잖아 있었다.
문제 접근 1을 통해 추가한 데이터 동기화 확인 코드때문에 새 아이템들을 로드할 때 아주 짧은 시간 No. ~로 보이면서 깜빡이었기에 이는 다시 삭제하였다.

profile
Reciprocity lies in knowing enough

0개의 댓글