반응형
Notice
Recent Posts
Recent Comments
Link
- Today
- Total
01-25 03:17
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 시각화
- 명령어
- barplot
- substr
- ios
- MVC
- 연산자
- Observable
- tapply
- 티스토리챌린지
- scheduledTimer
- SWIFT
- cocoapods
- deeplearning
- Optional
- Python
- Request
- swiftUI
- 딥러닝
- struct
- decode
- ReLU
- rxswift
- rest api
- r
- SQL
- HTTP
- sigmoid
- 오블완
- Linux
Archives
iOS 개발 기록 블로그
Xcode 16 + iOS 18 UICollectionView 크래시 원인 및 개선 방안: NSInternalInconsistencyException 본문
iOS
Xcode 16 + iOS 18 UICollectionView 크래시 원인 및 개선 방안: NSInternalInconsistencyException
crazydeer 2025. 1. 12. 18:44반응형
에러 로그
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Expected dequeued view to be returned to the collection view in preparation for display.
When the collection view's data source is asked to provide a view for a given index path,
ensure that a single view is dequeued and returned to the collection view.
Avoid dequeuing views without a request from the collection view.
For retrieving an existing view in the collection view, use:
- [UICollectionView cellForItemAtIndexPath:] or
- [UICollectionView supplementaryViewForElementKind:atIndexPath:].
Dequeued view:
<Geniet.HomeDABannerCell: 0x14d7e2700;
baseClass = UICollectionViewCell;
frame = (14040 0; 390 195);
layer = <CALayer: 0x300dab8c0>>;
Collection view:
<UICollectionView: 0x14d62ce00;
frame = (0 50; 390 195);
clipsToBounds = YES;
gestureRecognizers = <NSArray: 0x3002e2eb0>;
backgroundColor = <UIDynamicSystemColor: 0x3019969c0; name = systemBackgroundColor>;
layer = <CALayer: 0x300de69e0>;
contentOffset: {13651, 0};
contentSize: {30030, 195};
adjustedContentInset: {0, 0, 0, 0};
layout: <UICollectionViewFlowLayout: 0x14d63af80>;
dataSource: <Geniet.HomeHeaderView: 0x14d236700;
baseClass = UICollectionViewCell;
frame = (0 0; 390 344);
clipsToBounds = YES;
backgroundColor = UIExtendedGrayColorSpace 1 1;
layer = <CALayer: 0x300d26bc0>>>
원인 분석
발생 위치
아래 코드에 의해 크래시 발생
let destinationIndexPath = IndexPath(item: nextPage, section: 0)
if nextPage < self.daBannerIndex.count, self.daCollectionView.dataSource?.collectionView(self.daCollectionView, cellForItemAt: destinationIndexPath) != nil {
self.daCollectionView.scrollToItem(at: destinationIndexPath, at: .right, animated: true)
}
- ⚠️ self.daCollectionView.dataSource?.collectionView(self.daCollectionView, cellForItemAt: destinationIndexPath) != nil
위 코드 해석
- dataSource의 cellForItemAt: 메서드를 직접 호출
- UICollectionView가 셀을 dequeue하지 않았음에도 강제로 데이터 소스 메서드를 호출하는 비정상적인 동작
발생 이유
NSInternalInconsistencyException
UICollectionView는 특정 인덱스의 셀을 dequeue하도록 요청했지만, 해당 셀이 적절히 처리되지 않았다는 뜻
Expected dequeued view to be returned to the collection view in preparation for display
셀을 dequeue한 후, UICollectionView에 반환되지 않았음을 나타냄
도출
- 직접 호출된 cellForItemAt: 메서드는 시스템이 관리하는 UICollectionView와 동기화되지 않습니다.
- 시스템은 해당 셀이 표시될 준비가 되었는지 제대로 알지 못하며, 호출 과정에서 시스템 상태를 손상시킵니다.
- 따라서 크래시가 발생
개선 방안
- daCollectionView의 cellForItem(at:)를 사용하여 셀의 존재 여부를 확인
if nextPage < self.daBannerIndex.count {
let destinationIndexPath = IndexPath(item: nextPage, section: 0)
self.daCollectionView.scrollToItem(at: destinationIndexPath, at: .right, animated: true)
}
결론
- collectionView(_:cellForItemAt:)는 직접 호출하면 안 되는 메서드
- 크래시는 UICollectionView와 데이터 소스의 상태가 비정상적으로 동기화되었기 때문에 발생
- cellForItemAt: 호출을 제거하고, 데이터 유효성만 검증하도록 수정
추가로 기존 버전에서 발생하지 않았던 원인은 아래와 같습니다.
시스템 내부 구현 변화
- Xcode 16과 iOS 18 조합에서는 UICollectionView가 collectionView(_:cellForItemAt:) 메서드 호출 시 더 엄격한 동기화를 요구하도록 변경된 것으로 보입니다.
검증 로직 추가
- iOS 18에서는 NSInternalInconsistencyException을 통해 명시적으로 오류를 발생시킴으로써, 잘못된 호출을 방지하려고 한 것으로 보입니다.
추가 개념
collectionView(_:cellForItemAt:) 메서드:
UICollectionView가 dequeue하려고 할 때 보여줄 Cell을 반환하기 위해 내부적으로 호출되는 메서드
반응형
'iOS' 카테고리의 다른 글
Xcode 빌드 에러: 'Could not locate device support files' (Using Xcodes) (0) | 2025.01.14 |
---|---|
[Swift] 프로퍼티를 init 메서드에서 초기화, 선언 시 초기화 차이 (1) | 2024.09.11 |
Swift ReactorKit @Pulse 사용 목적, 예시, 일반 State와의 차이 (0) | 2024.06.01 |
iOS(Swift) 네비게이션 바 아이템 간격 조절 (imageInsets) (0) | 2022.10.10 |
iOS (Swift) CocoaPods 사용하기 4탄 (라이브러리 삭제하는 방법) (0) | 2022.07.19 |