TableView를 스크롤 하면 Cell의 값이 바뀌는 현상 ㅜㅜ

안녕하세요!

앱개발을 하다가 이상한 현상을 발견해서 질문글 올립니다

영상으로 보여드리는 게 제일 빠를 것 같아서 영상 첨부합니다.

스크롤을 하니까 cell 안에 있는 view가 막 바뀝니다;;
해당 view가 어떨 때는 원하는 형태(값)로 나타나는데, 스크롤하면 막 자꾸 다른 형태(값)으로 바뀝니다.
그런데 또 앱이 크래쉬가 나지는 않습니다.
차라리 크래쉬가 나버리면 왜 그런지 파악이 될텐데, log를 찍어봐도 데이터는 정상적인 것 같은데
출력만 자꾸 이상하게 나오네요 ㅜㅜ

테이블뷰가 한 번에 모든 cell을 뿌리는 게 아니라 화면에 보이는 cell을 뿌리는 느낌(?)인 건 알고 있는데
정확한 동작 방식을 몰라서 그런건가 싶습니다.
이 동작 방식과 연관이 있는 문제인 것 같긴 합니다.
테이블 뷰가 뿌려진 직후의 화면에 있는 셀들은 값이 다 정상인데, 스크롤해서 화면을 내려서 나오는 셀들부터 값이 이상해지기 시작합니다 ㅜㅜ

영상에서 스크롤 할 때마다 형태가 바뀌는 view는

override func draw(_ rect: CGRect)

로 그려지게끔 구현해 뒀습니다. 여기서 문제가 생기는 건가 싶기도 하네요 ㅜㅜ

잘 모르겠어서 일단 코드를 첨부합니다.

TableView의 cell

routePreviewBarView가 영상에서 모양이 바뀌는 색칠된 선에 해당하는 view입니다.

TableViewController에서 cell을 뿌리는 부분

RoutePreviewBarView의 draw()

도움 부탁드립니다!

해결 되었습니다!

draw()에 관련된 문제가 맞았네요.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

요 함수에서

return cell

하기 전에

cell.routePreviewBarView.setNeedsDisplay()

이 메소드를 호출해 주었습니다.

정확한 설명이 어려워서 링크로 첨부합니다!

좋아요 1

셀 객체에서 검색 결과 배열을 직접 접근하는 방식보다는 다음 두 가지 중 하나를 선택하는 것을 추천합니다.

  • 데이터소스에서 직접 셀 객체를 통해서 값을 출력하기(셀의 역할은 데이터를 출력하는 역할만 수행)
  • 셀 객체에게 출력해야 하는 객체를 통째로 넘기기

지금 코드는 다음 두 가지가 섞여 있습니다.

  • 데이터소스가 셀의 아웃렛을 이용해서 데이터 출력(totalTimeLabel, routeInfoLabel)
  • 인덱스를 넘겨줘서, 셀이 직접 검색 결과 배열에 접근하기

다음과 같은 코드도 고려해보세요.

// 데이터소스에서 셀 객체로 데이터 주입

cell.routeInfo = routeSearchList[indexPath.row - 1] // -1은 왜 하나요?

// 셀 클래스

class RouteSearchResultCell : UITableViewCell {
    var routeInfo: RouteInfo {
        didSet {
            totalTimeLable.text = "..."
            routeInfoLabel.text = "..."
            routePreviewBarView.SomeLabel.text = "..."           
        }
    }
}
좋아요 4

Latte is~~ 라떼는 말야~~ ㅎㅎ

오래간만에 반가운 접근 법이 보여서… iPhoneOS 앱을 GCC 에서 컴파일 하던 시절 이야기를 해볼까 합니다… :smile:

위에서 설명을 잘 해주셨는데요, 테이블 뷰 셀의 레이어에 직접 그리는 방식을 처음 선보였던 앱이 트위터 클라이언트 였던걸로 기억합니다.

그때나 지금이나 트위터 클라이언트는 참… 도전거리 였죠… :slight_smile: iPhoneOS 3.x 시절에, 10만건 이상 되는, 높이가 각각 다르고, 각 컨텐츠 별로 정규식으로 뒤져서 해시태그나 링크를 뽑고, 그 위에 버튼을 쪼개서 올리던 시절… :smile:

여담이지만, 직접 그리면, 초반에 살짝 버벅 거리지만, 바로 GPU 가 퍼포먼스를 올려주면서 하드웨어 가속으로 부드럽게 동작해 줬지요… ^^
제일 빠른 방법이었고, 30만개 정도의 글은 걍 부담없이 한방에 처리되죠. (어떻게 아냐고 물어보면…?! ㅎㅎ)

  • 그러고보니, 그땐 sqlite3 에다가 넣고 빼내면서 그렇게 했었… 쿨럭;;

암튼 저 방식은 트위터에서 길을 열고, 얼마 안되서 애플 공식 샘플로 테이블뷰의 셀에 값을 출력하는 네가지 방법이라는 유명한 예제가 나오게 됩니다. 요즘도 있으려나…?

질문 작성자의 윗 코드에서 setNeedsDisplay 를 호출하는 것도 좋지만, 개인적으로는 cell 을 dequeuing 하지말고, 바로 셀 인스턴스를 만들어서 뿌려버리는 게 더 빠를꺼에요… ㅎㅎㅎㅎㅎ (100% 보장은 안합니다.ㅎㅎ) - 아, 근데 그러면 열심히 만든 프로토타입 셀을 못쓰겠구나… :smile:

걍, 추억은 방울 방울, 라떼는 말야~~ 였습니다. 굿나잇~

좋아요 2

네, 당시에 테이블 뷰 셀 퍼포먼스에 대한 WWDC 세션도 있었죠. 이제는 테이블 뷰가 하는 일을 콜렉션 뷰에게 다 떠넘기는 추세라… 테이블 뷰도 레거시 취급받을 날이 왔는데… SwiftUI 가 판을 엎어버리는…ㅎ

그나저나 Zedd 님은 학생들이 애정하는 블로거군요. 다음에는 특강으로 한 번 모셔야 겠네요.

좋아요 1

상세한 답변 감사합니다!

확실히 저렇게 코드를 고치니까 시뮬레이터에서 버벅이면서 작동하더라구요 ㅜㅜ

셀을 뿌리는 데도 이렇게나 다양한 방법이 있다는 것 배워갑니다 ㅎㅎ

좋아요 1

Zedd님 블로그는 뭔가 스택오버플로우처럼 해답 코드만 딱 나와있는 게 아니라

documents부터 차근차근 해설해주시는 타입이라서

제 질문 같은 상황처럼 정확한 원인을 알지 못하는 경우에 도움이 많이 되는 것 같네요 ㅎㅎ

좋아요 1

앗 ㅎㅎ 부끄럽네요 ㅋㅋ 발표 기한 맞추느라고 코드가 많이 부족합니다 ㅎㅎ…

감사합니다!!

좋아요 1