libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: self.supplementaryViewProvider || (self.supplementaryReuseIdentifierProvider && self.supplementaryViewConfigurationHandler)'
terminating with uncaught exception of type NSException
로그를 대충 읽어보니 supplementaryViewProvider와 supplementaryReuseIdentifierProvider가 만족되지 않는다네.
아래 코드처럼 collectionView에 헤더뷰 register()를 해줬는데 dequeueReusableSupplementaryView 도 같이 해줘야하나보다.
내 코드 >
	// 1. Configure collectionView
	private lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: createLayout()).then {
        $0.register(TopBannerCollectionViewCell.self, forCellWithReuseIdentifier: TopBannerCollectionViewCell.cellIdentifier)
        $0.register(HomeCategoryCollectionViewCell.self, forCellWithReuseIdentifier: HomeCategoryCollectionViewCell.identifier)
        $0.register(CommunityMainCollectionViewCell.self, forCellWithReuseIdentifier: CommunityMainCollectionViewCell.identifier)
        
        // Header register
        $0.register(HomeTitleHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeTitleHeaderView.identifier)
        $0.backgroundColor = .clear
    }
    
    // 2. configure header
    viewModel.datasource.supplementaryViewProvider = { [weak self] view, kind, index in
    	return self?.collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeTitleHeaderView.identifier, for: index)
    }기존에는 UICollectionViewDelegate의 "collectionView(:viewForSupplementaryElementOfKind:at:)" 함수 내에서 dequeueReusableSupplementaryView를 작성했다면
Diffable Datasource를 사용할 땐, "supplementaryViewProvider" 로 구현할 수 있음.
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath: does not match the element kind it is being used for. When asked for a view of element kind 'HomeTitleHeaderView' the data source dequeued a view registered for the element kind 'UICollectionElementKindSectionHeader'.'
terminating with uncaught exception of type NSException
이번엔 또 읽어보니 element kind가 매칭이 안된다..? 뭘까..
내가 알고있던 kind는 header인지 footer인지 구분하는 거고 헤더면 "UICollectionView.elementKindSectionHeader" 이거 쓰면 되는거 아니였냐구..!
내 코드 >
	// collectionView register header
    collectionView.register(CommunityMainCollectionViewCell.self, forCellWithReuseIdentifier: CommunityMainCollectionViewCell.identifier)
    
    // header reusable view dequeue
	collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeTitleHeaderView.identifier, for: index)흠,, 잘 넣어준 것 같은데 다시 잘 찾아보니...
이유를 찾았다.. 맞아 코드는 거짓말을 안하지 ㅠㅠㅠ 항상 사람이 문제야....
	// item, group 관련 코드 생략
    
    let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(56))
    let headerElement = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize,
                                                                    elementKind: HomeTitleHeaderView.identifier, // 띠용..
                                                                    alignment: .topLeading)
   	section.boundarySupplementaryItems = [headerElement]휴.. layout 잡아주는 부분에서 headerItem elementKind에 reuseIdentifier를 넣어주고 있... ㅠㅠ
서로 값이 다르니 당연히 오류가 날 수 밖에 ㅎㅎ
저 부분을 "UICollectionView.elementKindSectionHeader" 로 넣어주니 에러 없이 잘 나온다!
어차피 kind는 string이기 때문에 직접 string 만들어서 넣어줘도 상관은 없고 값만 서로 동일하면 에러 안남!
.
.
.
이거 때문에 열심히 구글링 해보다가 cell 과 header/footer register()를 해주는 방식이 기존과는 다른게 있길래 그거도 적용해 봤는데 잘 됨! 하지만 그건 iOS 14 이상에서만 가능..ㅎ
우리 앱은 iOS 13이 최소 지원 버전이라.. 버전을 올리자 할수도 없고 ㅠㅠ
이틀 내내 고생하다 원인을 찾고나니 허무.. 앞으론 더 꼼꼼히 봐보자!
코드 ex)
	// cell registrations
    
	let topBannerCellRegistration = UICollectionView.CellRegistration<TopBannerCollectionViewCell, [Banner]> { (cell, indexPath, banner) in
		cell.setData(banners: banner)
    }
	let categoryCellRegistration = UICollectionView.CellRegistration<HomeCategoryCollectionViewCell, HomeServiceMenu> { (cell, indexPath, homeMenu) in
		// ... (생략)
	}
	let macapickCellRegistration = UICollectionView.CellRegistration<CommunityMainCollectionViewCell, Story> { (cell, indexPath, story) in
		// ... (생략)
	}
	let headerRegistration = UICollectionView.SupplementaryRegistration<HomeTitleHeaderView>(elementKind: HomeTitleHeaderView.identifier) { supplementaryView, elementKind, indexPath in
		// ... (생략)
	}
    
    // datasource에 적용
    
    viewModel.datasource = UICollectionViewDiffableDataSource<HomeSection, HomeDataItem>(collectionView: collectionView, cellProvider: { collectionView, indexPath, listItem in
		switch listItem {
		case .topBanner(let banners):
			let cell = collectionView.dequeueConfiguredReusableCell(
            	using: topBannerCellRegistration, for: indexPath, item: banners
			)
			return cell
		.
        .
        .
        (생략)
        }
	})
        3번째 섹션에 header view 잘 적용된 거 확인~~!!
출처:
https://jamesrochabrun.medium.com/uicollectionviewdiffabledatasource-and-decodable-step-by-step-6b727dd2485
https://swiftsenpai.com/development/reload-diffable-section-header/