如何将Model与Cell值更新至私有泛型TableView配置属性?
Alright, let's break down how to solve this problem. Since Swift is a statically typed language, we can't directly change the type of already-declared private properties at runtime. Instead, we need to refactor our code to use generics strategically, so it can adapt to different type pairs like Industry/IndustryCell or Company/CompanyCell.
第一步:统一类型的协议约束
First, let's make sure our data models and cells share common protocols. This gives us a way to enforce consistency across different types while keeping flexibility:
// 定义数据模型的通用协议 protocol BusinessModel {} extension Company: BusinessModel {} extension Industry: BusinessModel {} // 定义TableViewCell的通用协议 protocol BusinessCell: UITableViewCell {} extension CompanyCell: BusinessCell {} extension IndustryCell: BusinessCell {}
第二步:将当前类改造为泛型类
The cleanest approach is to turn your class into a generic one, so the type of tableConfig and tabledata is determined when you instantiate the class:
class BusinessTableHandler<Model: BusinessModel, Cell: BusinessCell> { // 私有属性现在由泛型参数决定类型 private var tableConfig: TableViewConfig<Model, Cell>? private var tabledata = [Model]() { didSet { tableConfig?.items = tabledata } } // 初始化时可以直接创建对应类型的tableConfig init() { tableConfig = TableViewConfig<Model, Cell>() } // 示例:添加数据的方法 func addData(_ newItems: [Model]) { tabledata.append(contentsOf: newItems) } }
第三步:根据外部条件实例化泛型类
When you confirm that model is of type Industry and companyCell is IndustryCell, you just instantiate the generic class with those specific types:
// 根据外部条件选择实例化的类型 var tableHandler: Any? if model is Industry, companyCell is IndustryCell { tableHandler = BusinessTableHandler<Industry, IndustryCell>() } else if model is Company, companyCell is CompanyCell { tableHandler = BusinessTableHandler<Company, CompanyCell>() }
替代方案:如果无法改造为泛型类——使用类型擦除
If refactoring the entire class to be generic isn't feasible, you can use type erasure to wrap different TableViewConfig instances into a unified type:
// 类型擦除的包装类,统一不同泛型TableViewConfig的接口 class AnyTableConfig { private let _updateItems: ([Any]) -> Void var items: [Any] { didSet { _updateItems(items) } } init<Model: BusinessModel, Cell: BusinessCell>(config: TableViewConfig<Model, Cell>) { _updateItems = { rawItems in guard let typedItems = rawItems as? [Model] else { return } config.items = typedItems } items = config.items as [Any] } } // 改造原有类 class YourExistingClass { private var tableConfig: AnyTableConfig? private var tabledata = [Any]() { didSet { tableConfig?.items = tabledata } } var model: BusinessModel? var companyCell: BusinessCell? // 更新配置的方法 func syncTableConfigWithCurrentTypes() { guard let modelType = type(of: model), let cellType = type(of: companyCell) else { return } switch (modelType, cellType) { case (is Industry.Type, is IndustryCell.Type): let typedConfig = TableViewConfig<Industry, IndustryCell>() tableConfig = AnyTableConfig(config: typedConfig) tabledata.removeAll() // 清空旧数据,准备接收Industry类型的数据 case (is Company.Type, is CompanyCell.Type): let typedConfig = TableViewConfig<Company, CompanyCell>() tableConfig = AnyTableConfig(config: typedConfig) tabledata.removeAll() default: break } } }
关键注意点
- Swift's static type system prevents changing property types after declaration, so we rely on generics or type erasure to handle multiple type pairs.
- Using protocols ensures that all our model/cell types behave consistently, avoiding messy type checks.
- For larger codebases, consider adding a factory pattern to create
TableViewConfiginstances, which will clean up the switch/case logic.
内容的提问来源于stack exchange,提问作者user11100093

