iOS继承场景下父控制器配置及Filter代理订阅问题求助
iOS控制器继承链中父控制器配置方案
针对你的控制器继承链MenuViewController → FilterCollectionViewController → CollectionViewController → MapsViewController,要在MapsViewController中配置FilterCollectionViewController的代理,需要解决三个核心问题:代理属性的访问权限、父类方法的逻辑错误、代理赋值时机。
1. 暴露Filter层的代理属性
CollectionViewController作为FilterCollectionViewController的直接子类,默认无法直接访问父类的代理属性,需要在CollectionViewController中添加对父类代理的访问入口:
class CollectionViewController: FilterCollectionViewController { // 新增:暴露Filter层的代理属性,让子类可访问 override var handlerFilterCellDelegate: IHandlerFilterCollectionDelegate! { get { super.handlerFilterCellDelegate } set { super.handlerFilterCellDelegate = newValue } } override var delegateSettingFilterCell: ISettingFilterCollectionDelegate! { get { super.delegateSettingFilterCell } set { super.delegateSettingFilterCell = newValue } } // 原有的其他代码保持不变... }
2. 修正FilterCollectionViewController的代理调用错误
在FilterCollectionViewController的collectionView(_:didSelectItemAt:)方法中,错误调用了registerCell,应该触发代理的itemSelect方法:
extension FilterCollectionViewController: UICollectionViewDataSource, UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { // 替换原错误代码,调用代理的点击方法 handlerFilterCellDelegate.itemSelect(index: indexPath.row) } // 原有的其他代码保持不变... }
3. 调整MapsViewController的代理赋值时机
父类的viewDidLoad会在子类初始化后优先执行,需要确保代理在父类配置UI前完成赋值,可调整初始化逻辑:
final class MapsViewController: CollectionViewController { init(menuDelegate: IMenuDelegate, itemMenu: MenuItem) { super.init() // 先设置Filter层的代理,再配置其他内容 handlerFilterCellDelegate = self delegateSettingFilterCell = self headerMenu = HeaderMenuViewController(menuItem: itemMenu, delegate: menuDelegate) handlerCellDelegate = self delegateSettingCell = self print("Maps view controller \(itemMenu)") } // 实现Filter代理方法 extension MapsViewController: IHandlerFilterCollectionDelegate { func itemSelect(index: Int) { // 处理筛选器单元格点击逻辑,比如更新筛选条件 print("Filter cell selected at index: \(index)") } } extension MapsViewController: ISettingFilterCollectionDelegate { func createCell(collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // 自定义筛选器单元格创建逻辑 let filterModel = modelFilterForDisplay[indexPath.row] if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FilterCell.reuseIdentifier, for: indexPath) as? FilterCell { cell.titleLabel.text = filterModel.title return cell } return UICollectionViewCell() } func registerCell(collectionView: UICollectionView) { collectionView.register(FilterCell.self, forCellWithReuseIdentifier: FilterCell.reuseIdentifier) } func calculateCellSize(screenWidth: CGFloat) -> CGSize { // 自定义筛选器单元格尺寸 return CGSize(width: 100, height: 40) } } // 原有的其他代码保持不变... }
额外注意事项
- 访问权限:确保所有代理属性、父类需要被子类访问的属性都设置为
open或public,避免访问限制 - 初始化顺序:父类的
viewDidLoad会在子类初始化后立即执行,所以代理赋值要优先于父类的UI配置逻辑 - 数据传递:如果需要在
MapsViewController中更新筛选器数据,可以给FilterCollectionViewController添加公开的更新方法,比如:
然后在class FilterCollectionViewController: MenuViewController { // 新增:公开更新筛选数据的方法 func updateFilterData(_ data: [IFilterCollectionModel]) { modelFilterForDisplay = data collectionFilterView.reloadData() } }MapsViewController中直接调用updateFilterData即可。
内容的提问来源于stack exchange,提问作者Steven Kirke
相关产品推荐
相关产品推荐

