如何在UICollectionViewCompositionalLayout中创建装饰视图并解决注册错误
问题:UICollectionViewCompositionalLayout装饰视图注册失败报错
我尝试在UICollectionViewCompositionalLayout中添加装饰视图,编写了以下代码:
创建布局Section的代码
func createListTableSection(using section: Section) -> NSCollectionLayoutSection { let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1)) let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize) layoutItem.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8) let layoutGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.93), heightDimension: .fractionalWidth(0.5)) let layoutGroup = NSCollectionLayoutGroup.horizontal(layoutSize: layoutGroupSize, subitems: [layoutItem]) let layoutSection = NSCollectionLayoutSection(group: layoutGroup) layoutSection.orthogonalScrollingBehavior = .groupPagingCentered layoutSection.decorationItems = [NSCollectionLayoutDecorationItem.background(elementKind: RoundedBackgroundView.reuseIdentifier)] let layout = UICollectionViewCompositionalLayout(section: layoutSection) layout.register(RoundedBackgroundView.self, forDecorationViewOfKind: RoundedBackgroundView.reuseIdentifier) return layoutSection }
RoundedBackgroundView实现代码
class RoundedBackgroundView: UICollectionReusableView { static let reuseIdentifier = "RoundedBackgroundView" private var insetView: UIView = { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = .secondarySystemFill view.layer.cornerRadius = 15 view.clipsToBounds = true return view }() override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear addSubview(insetView) NSLayoutConstraint.activate([ insetView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 15), trailingAnchor.constraint(equalTo: insetView.trailingAnchor, constant: 15), insetView.topAnchor.constraint(equalTo: topAnchor), insetView.bottomAnchor.constraint(equalTo: bottomAnchor) ]) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
运行时触发错误:
线程1:"无法出列类型为RoundedBackgroundView的装饰视图——必须注册为类、nib或在故事板中连接原型"
解决方案
错误原因
你在createListTableSection函数里临时创建了一个UICollectionViewCompositionalLayout实例并注册了装饰视图,但这个实例并没有被实际使用——函数返回的是layoutSection,最终CollectionView使用的是其他地方创建的Layout实例,导致注册的装饰视图不生效。
修复步骤
- 拆分函数职责:让
createListTableSection只负责创建返回NSCollectionLayoutSection,移除内部创建Layout和注册视图的代码。 - 在正确的位置注册:在创建最终赋值给CollectionView的Layout实例时,注册装饰视图。
修改后的代码
调整后的createListTableSection函数
func createListTableSection(using section: Section) -> NSCollectionLayoutSection { let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1)) let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize) layoutItem.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8) let layoutGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.93), heightDimension: .fractionalWidth(0.5)) let layoutGroup = NSCollectionLayoutGroup.horizontal(layoutSize: layoutGroupSize, subitems: [layoutItem]) let layoutSection = NSCollectionLayoutSection(group: layoutGroup) layoutSection.orthogonalScrollingBehavior = .groupPagingCentered layoutSection.decorationItems = [NSCollectionLayoutDecorationItem.background(elementKind: RoundedBackgroundView.reuseIdentifier)] return layoutSection }
在创建CollectionViewLayout的地方注册装饰视图
// 示例:在ViewController的viewDidLoad或配置CollectionView的代码中 let targetSection = Section(...) // 你的Section实例 let listSection = createListTableSection(using: targetSection) // 创建真正要绑定给CollectionView的Layout实例 let compositionalLayout = UICollectionViewCompositionalLayout(section: listSection) // 在这里注册装饰视图 compositionalLayout.register(RoundedBackgroundView.self, forDecorationViewOfKind: RoundedBackgroundView.reuseIdentifier) // 赋值给CollectionView collectionView.collectionViewLayout = compositionalLayout
额外注意事项
确保RoundedBackgroundView的reuseIdentifier没有与其他复用视图的标识重复,避免注册冲突。
内容的提问来源于stack exchange,提问作者user214155
相关产品推荐
相关产品推荐

