작성
·
174
1
답변 1
1
아 네 안녕하세요 kimkim333 님 :)
이해하시기 쉽게, 테이블뷰라고 가정을 해볼께요..
단순하게, 셀에 번호가 0번부터 9번까지 매겨져서..
(현재) 10개의 테이블뷰 셀이 하나의 화면에 표시된다고 가정해보고...
(이것보다 아래의 테이블뷰 셀들이 스크롤해서 올렸을때, 표시될 예정이라고 생각해 보시면)
만약에,
테이블뷰를 빠르게 스크롤해서 이미 영역을 지나가서
지금 현재는 셀의 번호가 대략 한 12 ~ 21 정도를 보여주고 있는 잠깐의 시간이라고
가정해 보시면..
인덱스패스(indexPath) 자체는 정확하게, 해당 셀들이 표시해야 하는 이미지를
명확하게 순서를 집어낼 수 있습니다. (아주 빠르게 위 아래로 스크롤 한다고 치더라도
인덱스패스(indexPath)의 순서는 변하지 않습니다.)
그런데, (만약에 셀을 전달한다고 가정하면) cell자체는 (아시는 바와 같이) 재사용이
되기 때문에 셀 자체를 전달했을때..
순서가 완전히 틀어질 수 있는 것이죠.
왜냐하면, 아까는 0번에 있던 셀이 예를 들어서 지금 현재는 다시 15번째로 가있고..
(아니면 20번째에 가 있을 수도 있고..등)
이런 순서의 뒤틀림 현상이 발생할 수 있는 것이죠.
(아까 0번째 셀에 있던 메서드의 실행이 오래걸리고.. 여전히 스크롤 한 후에도
동작하고 있는 중일 수도 있고.. 또한 이 셀 자체의 순서가 틀어지는 것때문에
==> 이미지의 순서가 틀어질 수 있게 됩니다.)
그래서, 사실 이것을 막는 기법에 대해
디테일한 구현이 몇가지 있는데,
물론 일반적으로 GCD-final 에서 제가 넣어놓은 예제보다는
Concurrency-Better프로젝트에 넣어놓은 프로젝트가 (이런 기법을 구현하기 위한 측면에서)
더 실무에 가까운 편이긴합니다.
일반적으로 이런 기법을 구현하기 위해서
1) url이나, 데이터 모델 자체를 셀에 전달을 합니다.
(뷰컨트롤러의 cellForRowAt 에서 이미지를 그리기 보다는 셀 자체에서 이미지를 다운로드하는 메서드를 구현하는 방식으로 구현)
2) 이미지를 다운로드를 다 받은 시점에 다운로드 받기전의 url과 다운로드 받은 후의 url을 한번 더 확인을 해서
걸러주는 방식으로 또 한번 확인
이런 식으로 구현을 합니다.
말씀하신
if let cell = self.collectionView.cellForItem(at: indexPath) as? PhotoCell
이 부분의 코드는 indexPath를 걸러주는게 아니라, 단순하게 타입캐스팅에 대한 옵셔널 바인딩을 하고 있는 코드 입니다.
(GCD-final 프로젝트에서는 위에 말씀드린 2가지 기법을 사용하고 있는 것은 아니라, 셀을 빠르게 스크롤했을때 완벽하게 걸러주지는 못할꺼예요. 그나마 인덱스패스 순서는 꼬이지는 않는 정도를 구현해 놓은 것이고.. 이미지 다운로드 시작시점과 다운로드 후의 시점은 약간 다를 수 있기 때문에, 아주 빠르게 스크롤 한다면 이미지가 약간씩 다르게 표시될 수 있는 문제는 있을 것이라고 생각이 들어요.)
제가 말씀드린 2가지 기법의 논리에 따라 조금 더 정확하게 구현된 내용을 보시고 싶으시면
Concurrency-Better프로젝트에 CustomImageView에 구현되어 있는
if self.lastImgUrlUsedToLoadImage != url.absoluteString 이 부분을 보시면 됩니다.
그리고 말씀하신 이미지 자체를 클로저로 넘기는 방법은..
이미지를 어떤방식/어떤 코드로 다운로드 받아서 넘길지에 따라서
달라질 수도 있을 것 같아서, 지금 말씀주신 내용만 가지고 맞다 아니다를 판단하기는
조금 힘들 것 같습니다.. ^^;
(빠르게 스크롤 할때도 이미지 순서가 바뀌지 않는 방식으로 구현된 방법이 있다면
(인덱스패스와 이미지 순서를 확인할 수 있는 방법이 있으면) 가능할 것 같다는 생각은 드는데..
실제 그런방식의 코드는 봐야알 것 같습니다.)
강의를 수강해 주셔서 감사드리고!
많은 도움 되시기를 바랍니다. :)
앨런 드림
자세하게 답변해주신 덕분에 이해가 잘 되었습니다. 감사합니다.