[포켓몬 도감 앱 만들기] 트러블슈팅: 무한 스크롤 중 데이터가 바뀌는 문제

황석범·2025년 1월 2일
1

내일배움캠프_iOS_5기

목록 보기
56/76

문제 상황

스크롤을 빠르게 내렸다가 올리면 cell 위치에 잘못된 이미지가 들어가는 문제


문제 해결

  • self.viewModel.pokemonImageSubject.onNext(nil)을 호출하여 셀을 재사용할 때, 이전 셀에서 로드되었던 이미지 데이터를 초기화하여 새롭게 요청할 수 있게 하는 역할을 합니다.
 override func prepareForReuse() {
        super.prepareForReuse()
        self.imageView.image = nil
        self.disposeBag = DisposeBag()
        self.currentIndexPath = nil
        self.viewModel.pokemonImageSubject.onNext(nil)
    }

셀에서 구독하고 있는 subject가 초기값을 가지고 구독을 시작하면 가장 최근에 방출되었던 값을 받으며 구독을 시작하는 객체이기 때문

let pokemonImageSubject = BehaviorSubject<UIImage?>(value: nil)

1. 메모리 관리:

  • 이전에 로드된 이미지가 셀을 재사용할 때도 메모리에 남아 있을 수 있습니다. 이미지를 nil로 초기화하면 이전 이미지가 메모리에서 제거되고, 새 이미지가 로드될 때 더 이상 이전 이미지가 표시되지 않게 됩니다.

2. UI 일관성 유지:

  • 셀이 재사용되면 이미지가 계속 덮어씌워질 수 있습니다. 이전 이미지가 남아 있으면 화면에 불필요한 이미지를 표시하게 될 수 있습니다. onNext(nil)을 호출하여 이미지를 초기화하고, 이후에 새로운 이미지가 제대로 로드되도록 합니다.

3. 구독 클린업:

  • disposeBag을 초기화하여 셀을 재사용할 때마다 새로운 구독을 설정하게 됩니다. pokemonImageSubject.onNext(nil)을 호출하여 데이터 흐름을 초기화하고, 구독이 새로 시작되도록 할 수 있습니다.

4. 포켓몬 이미지 새로 요청하기:

  • 만약 이전에 구독한 이미지가 남아있다면, 셀을 재사용할 때 그 이미지가 중복해서 표시될 수 있습니다. onNext(nil)을 호출함으로써 이전 상태를 깨끗하게 지우고, 새로운 이미지 요청을 할 수 있도록 유도합니다.

PublishRelay로 바꾸는 것이 좋아 보인다. 바꿔보자

final class MainViewCellModel {
    private let disposeBag = DisposeBag()
    let pokemonImageRelay = PublishRelay<UIImage?>()
   
    func fetchPokemonImage(for id: Int) {
        NetworkManager.shared.fetchPokemonImage(for: id)
            .subscribe(onSuccess: { [weak self] image in
                self?.pokemonImageRelay.accept(image) // 값 방출
            }, onFailure: { [weak self] error in
                self?.pokemonImageRelay.accept(nil) // 실패 시 nil 방출 (필요에 따라)
            })
            .disposed(by: disposeBag)
    }
}

1. nil 값 문제 해결

  • PublishRelay는 BehaviorSubject처럼 초기값을 갖지 않으므로, 셀 재사용 시 nil을 강제로 전달할 필요가 없어집니다.

2. 불필요한 상태 초기화 제거

  • BehaviorSubject처럼 구독이 시작될 때마다 마지막 값이 전달되지 않기 때문에, 불필요한 값이 구독자에게 전달되지 않습니다.

3. 단순한 이벤트 흐름

  • PublishRelay는 이벤트만 전달하기 때문에 값의 상태를 추적할 필요가 없는 경우 적합합니다.

아래 리팩토링을 통해 문제 해결

리팩토링1

profile
iOS 공부중...

0개의 댓글

관련 채용 정보