UICollectionView에서 특정 cell이 그려지지 않는 이슈
UICollectionView에서 기본 고정값을 정해두고, 불특정한 크기의 이미지 로딩이 끝나면, 해당 셀에 delegate에서 reloadItemsAtIndexPaths를 호출하여 불러온 이미지의 크기만큼 셀의 높이를 지정해주려는 코드를 다음과 같이 작성했다.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
STImage *_moduleImage = [self getModuleImageAtIndexPath:indexPath];
return CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.width * ((_moduleImage.ratio) ? [_moduleImage.ratio floatValue] : 1));
}
다음은 UICollectionViewCell 을 상속받아 만든 클래스의 delegate
- (void)exhibitionViewHeaderBannerCellWillReload:(STExhibitionViewHeaderBannerCell *)cell {
NSIndexPath *reloadIndexPath = [self.collectionView indexPathForCell:cell];
[self.collectionView reloadItemsAtIndexPaths:@[reloadIndexPath]];
}
다음은 셀에서 이미지를 로드하고, 로드된 이미지의 비율(ratio)를 구해서 dataset으로 저장하는 코드
NSURL *requestImageURL = [NSURL thumbnailURLWithString:self.imageInfo.url withSize:self.imageView.frameSize];
[self.imageView sd_setImageWithURL:requestImageURL
placeholderImage:nil
options:SDWebImageHighPriority|SDWebImageProgressiveDownload
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if(self.imageInfo && !self.imageInfo.ratio) {
[self.imageInfo setRatio:[NSString stringWithFormat:@"%.5f",image.size.height / image.size.width]];
if(self.delegate && [self.delegate respondsToSelector:@selector(exhibitionViewHeaderBannerCellWillReload:)]) {
[self.delegate exhibitionViewHeaderBannerCellWillReload:self];
}
}
}];
이런식으로 이쁘게(?) 짜 놓고 잘 돌아갈거라는 생각을 했다..
2016-05-31 10:28:18.116 KakaoStyle[20153:2677155] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][240]- 2/0 height : 375.000000
2016-05-31 10:28:18.116 KakaoStyle[20153:2677155] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][240]- 2/1 height : 375.000000
2016-05-31 10:28:18.116 KakaoStyle[20153:2677155] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][240]- 4/0 height : 375.000000
2016-05-31 10:28:18.116 KakaoStyle[20153:2677155] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][240]- 4/1 height : 375.000000
최초 로딩시 기본값인 375.f가 세팅된다.
2016-05-31 10:41:00.953 KakaoStyle[20377:2749211] -[STExhibitionViewController exhibitionViewHeaderBannerCellWillReload:][516]- 2/0 will reload
2016-05-31 10:41:00.955 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 600.000009
2016-05-31 10:41:00.955 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 375.000000
2016-05-31 10:41:00.955 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 375.000000
2016-05-31 10:41:00.955 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 375.000000
두번째 섹션의 첫번째 로우가 이쁘게 리로딩 됨.
2016-05-31 10:41:00.960 KakaoStyle[20377:2749211] -[STExhibitionViewController exhibitionViewHeaderBannerCellWillReload:][516]- 2/1 will reload
2016-05-31 10:41:00.961 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 600.000009
2016-05-31 10:41:00.961 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 600.000009
2016-05-31 10:41:00.961 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 375.000000
2016-05-31 10:41:00.961 KakaoStyle[20377:2749211] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 375.000000
두번째 로우 역시 이쁘게 리로딩됨.
어라 두번째 로우가 안보인다. 리로드 코드를 주석처리 하고 다시 한번 돌려봤다.
분명 두번째 로우가 있었는데 리로드를 하는 과정에서 셀이 날아갔다. 여기부터 멘붕.
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
UICollectionView DataSource 관련 메소드를 하나씩 다 디버깅 걸어서 왜 cell이 그려지지 않는지 하루종일 삽질을 했다.
네번째 섹션도 마찬가지 첫번째 row만 나오고 두번째 row는 노출되지 않았다.
2016-05-31 10:47:25.359 KakaoStyle[20501:2792252] -[STExhibitionViewController exhibitionViewHeaderBannerCellWillReload:][516]- 4/0 will reload
2016-05-31 10:47:25.360 KakaoStyle[20501:2792252] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 600.000009
2016-05-31 10:47:25.360 KakaoStyle[20501:2792252] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 600.000009
2016-05-31 10:47:25.360 KakaoStyle[20501:2792252] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 304.053761
2016-05-31 10:47:25.360 KakaoStyle[20501:2792252] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 375.000000
여기서 문제를 바로 발견했어야 했는데. 바로 그것이다. height이 미묘한 소숫점으로 구성되어 있다는 그것.
CGSize는 CGFloat으로 구성된 구조체인데, 왜 float 한 값이 들어갔다고 그리질 못하냐.. 아마도 UICollectionViewFlowLayout 이 CollectionView를 구성하는 과정에서 소숫점 계산을 잘못하는 것 같다.
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
예전에도 여기서 섹션과 로우를 잘 못 계산해서 하나씩 로우가 사라지던 이슈가 있었던게 기억난다.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
STImage *_moduleImage = [self getModuleImageAtIndexPath:indexPath];
return CGSizeMake(self.view.bounds.size.width, floorf(self.view.bounds.size.width * ((_moduleImage.ratio) ? [_moduleImage.ratio floatValue] : 1)));
}
CGSize의 height을 floorf로 이쁘게 감싸 줬더니 깔끔하게 해결 됐다.
2016-05-31 10:54:03.208 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 375.000000
2016-05-31 10:54:03.208 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 375.000000
2016-05-31 10:54:03.209 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 375.000000
2016-05-31 10:54:03.209 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 375.000000
2016-05-31 10:54:03.221 KakaoStyle[20593:2829145] -[STExhibitionViewController exhibitionViewHeaderBannerCellWillReload:][516]- 2/0 will reload
2016-05-31 10:54:03.221 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 600.000000
2016-05-31 10:54:03.222 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 375.000000
2016-05-31 10:54:03.222 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 375.000000
2016-05-31 10:54:03.222 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 375.000000
2016-05-31 10:54:03.230 KakaoStyle[20593:2829145] -[STExhibitionViewController exhibitionViewHeaderBannerCellWillReload:][516]- 2/1 will reload
2016-05-31 10:54:03.231 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 600.000000
2016-05-31 10:54:03.231 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 600.000000
2016-05-31 10:54:03.231 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 375.000000
2016-05-31 10:54:03.231 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 375.000000
2016-05-31 10:54:05.059 KakaoStyle[20593:2829145] -[STExhibitionViewController exhibitionViewHeaderBannerCellWillReload:][516]- 4/0 will reload
2016-05-31 10:54:05.059 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 600.000000
2016-05-31 10:54:05.059 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 600.000000
2016-05-31 10:54:05.059 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 304.000000
2016-05-31 10:54:05.059 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 375.000000
2016-05-31 10:54:05.728 KakaoStyle[20593:2829145] -[STExhibitionViewController exhibitionViewHeaderBannerCellWillReload:][516]- 4/1 will reload
2016-05-31 10:54:05.728 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/0 height : 600.000000
2016-05-31 10:54:05.729 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 2/1 height : 600.000000
2016-05-31 10:54:05.729 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/0 height : 304.000000
2016-05-31 10:54:05.729 KakaoStyle[20593:2829145] -[STExhibitionViewController collectionView:layout:sizeForItemAtIndexPath:][238]- 4/1 height : 210.000000
모처럼 코딩하다가 기분 좋은 순간이었음.. 감격스러워 비명까지 지름 ㅠㅠ
한 줄 요약 UITableViewCell이나 UICollectionViewCell 크기를 CGSize로 생성할 땐 반드시 floor나 ceil를 써서 소숫점을 날려버리자.














