0810 새싹 28회차 정리 - TableView/CollectionView Cell
iOS 앱 개발자 데뷔 과정 28회차
#1. Checklist
- awakeFromNib
셀 UI를 초기화하는 메서드로, 재사용 매커니즘에 의해 일정 횟수 이상 호출되지 않는다.
변경되지 않는, 고정적인 틀과 같은 UI를 설정할 때 사용하면 불필요한 호출을 줄일 수 있다.
- prepareForReuse
셀이 재사용 될 때 초기화 하고자 하는 값을 넣으면 셀이 재사용되며 발생할 수 있는 오류를 해결할 수 있다.
즉, cellForRowAt에서 모든 indexPath.item에 대한 조건을 작성하지 않아도 된다.
- awakeFromNib과 prepareForReuse, 그리고 cellForRowAt과 cellForItemAt 호출 시점 알아보기
* 현재 뷰는 TableView의 안에 CeollectionView가 들어있는 형태이다.
1. TableViewCell awakeFromNib
2. TableView cellForRowAt
3. CollectionView cellForItemAt
4. CollectionViewCell awakeFromNib
CeollectionView의 셀을 계속 움직여보면, 재사용 메너키즘에 의해 이미 호출된 awakeFromNib은 더 이상 호출되지 않는다.
각각 print를 입력해보면 위의 순서대로 호출되는 것을 확인할 수 있다.
awakeFromNib이 cellForRowAt보다 먼저 실행된다고 알고 있었는데, 왜 3번과 4번은 반대일까?
TableView에 CellectionView가 들어있기 때문에, CellForRowAt에서 CollectionView가 미리 호출되기 때문이다.
- dequeueReusableCell
dequeueReusableCell을 설정할 때 주의해야 하는 것이, let cell 을 초기화할 때 사용하는 테이블뷰/컬렉션뷰의 명칭이다.
만약 내부 매개변수가 아닌 특정 아웃렛을 사용할 경우 모든 셀이 해당 아웃렛을 재사용하게 된다.
- reloadData
빌드했을 때, 셀을 빠르게 넘기다 보면 Index Out of Range 에러가 발생하는 것을 볼 수 있다.
그래서 print를 통해 셀의 indexPath를 출력해보면, 요소보다 많은 수의 Index가 출력된다.
하나의 컬렉션뷰나 테이블뷰일땐 문제가 없었던 것 같은데, 이유가 뭘까?
테이블뷰 안에 컬렉션뷰를 넣는 복합적인 형태이다보니, 테이블셀도 재사용 되어야 하고 컬렉션셀도 재사용 되어야 한다.
따라서 인덱스가 꼬이기 쉬운 구조가 되는 것이다.
내 잘못은 아닌거같아서 뭔가 억울하기도 하다...
이 오류를 해결하기 위해서는, CellForRowAt (더 아래에 있는, 큰 객체 기준) 에서 내부에 있는 View를 리로드해줘야 한다.
이렇게 하면 테이블뷰의 셀이 재사용될 때 마다 컬렉션뷰가 초기화되기 때문에 인덱스가 꼬이지 않는다.
- dump
print와 유사하지만, dump를 사용하면 훨씬 깔끔하고 예쁜 모양으로 출력된다.
출력할 내용이 많을 때, 특히 배열 등의 결과를 보고 싶을 때 매우 적합할 것 같다.
- @escaping closure / completionHandler
callRequest ➡️ requestImage ➡️ View
순으로 데이터를 전달하며, 전과 마찬가지로 이스케이핑 클로저와 컴플리션핸들러를 이용했다.
조금 다른 점은 데이터를 이중 배열로 구성하기 위해 두번 전달하기 때문에 아래와 같은 형태가 된다.
requestImage 내부 코드를 반복문을 사용하지 않고 저렇게 작성한 이유는, completionHandler이기 때문이다.
completionHandler를 반복문으로 구성할 경우에는 순서를 보장받지 못하며, 언제 통신이 끝날지도 모른다.
그리고 만약 Limit이 있는 경우도 있을 수 있으니 (ex. 1초 내에 5번 이상의 요청은 Block) 반복문은 지양해야 한다.
- (옵션) Autoresizing / Frame Based Layout
Xcode에는 오토리사이징을 오토레이아웃 제약조건처럼 설정해주는 기능이 내부적으로 구현되어 있다.
이 기능은 디폴트가 true이지만, 오토레이아웃을 지정해주면 오토리사이징을 안 쓰겠다는 의미인 false로 상태가 자동으로 변경된다.
따라서 코드 기반 UI는 true일 것이고, 인터페이스 빌더 기반 레이아웃이 설정된 UI는 false일 것이다.
오토 리사이징과 오토 레이아웃이 모두 true라면 충돌로 에러가 발생한다.
- (옵션) translatesAutoresizingMaskIntoConstraints
print를 통해 Autoresizing이 현재 어떤 상태인지 Bool 값으로 알아낼 수 있다.
주석에도 적혀있듯이, 코드 기반으로 뷰를 추가하면 인터페이스 빌더 기반으로 만든 객체라도 true로 나올 수 있다.
#2. Assignment
- TMDB 프로젝트의 API 구성하기
27회차 과제로 구현한 레이아웃에서 TMDB로 가져온 데이터를 통해 테이블뷰/컬렉션뷰 구성
# 그 외
- 네비게이션 바 타이틀 컬러 변경
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]