✅ CollectionView
https://developer.apple.com/documentation/uikit/uicollectionview
이번 시간에는 드디어 CollectionView에 대해서 알아보았다.
테이블 뷰는 자신 있었는데, CollectionView가 너무나도 궁금했는데, 드디어 시작!!
✅ 컬렉션 뷰도 결국은 테이블 뷰와 비슷한 형식을 띄고 있다.
❗️주의사항❗️
- 스토리보드에서 CollectionView Controller가 아닌 CollectionView를 선택해서 UIView에 넣는 방식으로 만들 시, CollectionView를 Controller에 delegate및 dataSource를 연결해줘야 사용할 수 있다.
- 이는 테이블 뷰에서도 마찬가지로, 내가 가끔 이걸 하지 않아서 헤매인 적이 많다. 꼭꼭 기억하자.
1️⃣ UICollectionViewDataSource
여기에는 기본적으로 "몇개를 보여줄건지?", "셀은 어떻게 표현할건지?"에 대해서 프로토콜을 상속받아서 사용해야 한다.
🆚 TableViewDataSource와의 차이점
1. indexPath.row가 아닌 indexPath.item을 사용한다.
// UICollectionViewDataSource
// 몇개를 보여줄까요?
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.numOfBountyInfoList
}
// 셀은 어떻게 표현할까요?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GridCell", for: indexPath) as? GridCell else {
return UICollectionViewCell()
}
let bountyinfo = viewModel.bountyInfo(at: indexPath.item)
cell.update(info: bountyinfo)
return cell
}
2️⃣ UICollectionViewDelegate
여기에는 "셀이 클릭되었을 때 어떻게 할거야?" 라고 담고 있다.
메소드는 TableView와 비슷해서 didSelectItemAt 이라고 작성되어 있어서 이해하기가 쉽다.
// UICollectionViewDelegate
// 셀이 클릭되었을 때 어떻게 할까요?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("-->\(indexPath.item)")
performSegue(withIdentifier: "showDetail", sender: indexPath.item)
}
⭐️ 3️⃣ UICollectionViewDelegateFlowLayout
이 부분은 테이블뷰와 가장 크게 두드러진 차이점을 보여주는 지점이다.
UICollectionView의 경우 테이블 뷰 형식이 아니라 가로, 세로 등 여러개의 아이템을 배치할 수 있는데, 이에 따라서 레이아웃을 기기의 변화에 맞게 대응해줘야 한다.
이 부분을 온전히 이해하기 위해서는 레이아웃에 대한 이해와 더불어 수학적 사고가 요구된다.
아래의 코드를 같이 보자.
// UICollectionViewDelegateFlowLayout
// 셀의 사이즈가 디바이스 마다 조금씩 변경되어야 할 필요가 있어서 - 가로폭이 다르기 때문에
// cell size 계산할거다( 목표 : 다양한 디바이스에서 일관적인 디자인 보여주기 위해 )
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let itemSpacing : CGFloat = 10
let textAreaHeight : CGFloat = 65
let width : CGFloat = (collectionView.bounds.width - itemSpacing) / 2
let height : CGFloat = width * 10/7 + textAreaHeight
return CGSize(width: width, height: height)
}
위의 코드를 기반으로 레이아웃을 잡으면 아래와 같은 이미지의 형태를 띄게 된다. 그럼 한줄한줄 코드에 대해서 리뷰해 보자.
✅ 우선 위의 함수에서 return 값을 보면 CGSize(width, height)를 반환하고 있는데, 이를 테이블 셀의 각 아이템 컨테이너의 크기라고 생각하자.
bounds의 경우에는 자신만의 좌표를 가짐
frame의 슈퍼 뷰(상위 뷰)를 기준으로 좌표를 가짐
let itemSpacing : CGFloat = 10 // 아이템 간의 간격
let textAreaHeight : CGFloat = 65 // 글자가 위치할 간격
let width : CGFloat = (collectionView.bounds.width - itemSpacing) / 2 // 컬렉션뷰의 자신만의 자신의 좌표를 넓이로 삼아, 아이템 간의 간격을 뺴준 후 나누기 2
-> 여기 코드가 조금 봐야하는 지점인데, 나누기 2하는 이유는 기기의 전체 아이템을 2개 넣을 생각이라.
-> 이 부분에서 수학적인 사고가 요구되는데, Q. 만약에 3개를 넣고 싶으면 코드를 어떻게 수정해야 할까?
-> A. let width : CGFloat = (collectionView.bounds.width - 2 * itemSpacing) / 3
여백 공간도 셀이 늘어나는 만큼 조정되야 한다.
let height : CGFloat = width * 10/7 + textAreaHeight // width가 정해졌으면, 7:10 비율로 높이를 정하고, 글자가 들어갈 공간만큼 높이를 더 확보한다.
❗️여기서 주의할 점 : :Label을 크기를 고려해서 적절하게 잡아야 한다.
return CGSize(width: width, height: height) // 마지막으로 이 값을 리턴하면 끝!
여기까지가 UICollectionViewDelegateFlowLayout에 대한 기본적인 정보였다.
(추가)
✅ 간혹 우리가 코드를 올바르게 입력했음에도 뷰 구성이 제대로 되지 않는 경우가 있다.
❗️이건 흔히하는 실수인데, 우리가 코드를 작성할때,
Estimate Size 부분이 기본적으로 오토매틱으로 설정되어 있는데, 이 부분은 논으로 바꿔주어야 한다.
- 참고
https://zeddios.tistory.com/203
'Archive > 패캠(올인원)' 카테고리의 다른 글
ch12 애플뮤직st 음악앱 코드리뷰 (0) | 2021.06.24 |
---|---|
💈 ch11 현상금 랭킹앱 코드리뷰(Animation)💈 (0) | 2021.06.22 |
💈 ch11 Animation - 개념편💈 (0) | 2021.06.22 |
ch10 현상금 랭킹앱 코드리뷰(MVVM) (0) | 2021.06.21 |
ch10 MVVM 패턴 (0) | 2021.06.21 |