如何获取UICollectionView已注册补充视图类型?无需额外类的查询方法
关于UICollectionView已注册补充视图类型的查询方案
嘿,这个问题问到点子上了!很多开发者都会遇到类似的需求,我来给你详细说说:
核心结论:没有官方公开API直接查询
UICollectionView本身并没有提供公开的官方方法来直接获取已注册的补充视图类型——苹果把这些注册信息封装在了内部私有结构里,不会暴露给开发者。所以你想要的那种直接调用collectionView.supKinds()的原生方法是不存在的,除非你用私有API,但那会导致App审核不通过,还可能因为系统版本更新而失效,绝对不推荐在生产环境使用。
无需子类化的可行方案:关联对象+扩展
如果你不想子类化UICollectionView,我们可以用Objective-C关联对象给UICollectionView添加一个扩展,在每次注册补充视图时同步记录这些类型。这样既能保持原有代码结构,又能实现查询功能:
代码实现
import ObjectiveC import UIKit // 定义关联对象的唯一key private var registeredSupplementaryViewsKey = 0 extension UICollectionView { /// 获取所有已注册的补充视图类型,按elementKind分组 func registeredSupplementaryViewTypes() -> [String: [AnyClass]] { return objc_getAssociatedObject(self, ®isteredSupplementaryViewsKey) as? [String: [AnyClass]] ?? [:] } /// 包装系统注册方法,同步记录视图类型(纯代码注册) func registerSupplementaryView<T: UICollectionReusableView>(_ viewClass: T.Type, forSupplementaryViewOfKind elementKind: String) { // 先执行系统原生注册逻辑 register(viewClass, forSupplementaryViewOfKind: elementKind, withReuseIdentifier: String(describing: viewClass)) // 记录当前注册的类型 updateRegisteredSupplementaryViews(for: elementKind, adding: viewClass) } /// 包装系统注册方法,同步记录视图类型(Nib注册) func registerNibForSupplementaryView<T: UICollectionReusableView>(_ nib: UINib, viewClass: T.Type, forSupplementaryViewOfKind elementKind: String) { register(nib, forSupplementaryViewOfKind: elementKind, withReuseIdentifier: String(describing: viewClass)) // 记录当前注册的类型 updateRegisteredSupplementaryViews(for: elementKind, adding: viewClass) } // 私有辅助方法:更新注册记录 private func updateRegisteredSupplementaryViews(for elementKind: String, adding viewClass: AnyClass) { var registeredViews = registeredSupplementaryViewTypes() if var types = registeredViews[elementKind] { // 避免重复记录同一类型 guard !types.contains(viewClass) else { return } types.append(viewClass) registeredViews[elementKind] = types } else { registeredViews[elementKind] = [viewClass] } // 保存到关联对象 objc_setAssociatedObject(self, ®isteredSupplementaryViewsKey, registeredViews, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } }
使用方式
- 以后注册补充视图时,使用扩展里的
registerSupplementaryView(_:forSupplementaryViewOfKind:)或registerNibForSupplementaryView(_:viewClass:forSupplementaryViewOfKind:)方法,替代系统原生的注册方法。 - 当你需要查询已注册类型时,直接调用:
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) // 注册补充视图 collectionView.registerSupplementaryView(MyHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader) // 查询所有已注册类型 let registeredTypes = collectionView.registeredSupplementaryViewTypes() // 比如获取所有Header类型 let headerTypes = registeredTypes[UICollectionView.elementKindSectionHeader]
备选方案:子类化UICollectionView
如果你愿意子类化,也可以创建自定义的MyChildUICollectionView,重写所有注册补充视图的方法,在内部维护一个字典来记录注册类型。不过这种方式需要你在项目中统一使用子类,灵活性不如关联对象的方案。
内容的提问来源于stack exchange,提问作者iur
相关产品推荐
相关产品推荐

