Swift中泛型UIViewController子类类型转换失败问题求助
解决Swift泛型视图控制器类型转换失败问题
问题原因
Swift的泛型是不变的——即使AlertToastView继承自ToastContentView,ToastViewController<AlertToastView>和ToastViewController<ToastContentView>也是完全独立的类型,不存在父子关系,所以你无法将前者强制转换为后者。
解决方案
你可以通过定义非泛型的基类或协议实现类型擦除,让所有泛型子类都能被统一识别:
方案1:使用非泛型基类
先创建一个非泛型基类,让泛型ToastViewController继承它,所有具体子类(比如AlertViewController)会间接继承这个基类:
// 定义非泛型基类 class BaseToastViewController: UIViewController { // 声明公共属性/方法,供外部统一访问 var toastContentView: ToastContentView? { return view as? ToastContentView } } // 泛型子类继承非泛型基类 class ToastViewController<ContentViewType: ToastContentView>: BaseToastViewController { // 可选:重写属性返回具体泛型视图类型 override var toastContentView: ToastContentView? { return view as? ContentViewType } }
转场代码中直接转换为该非泛型基类:
if let toastVC = context.viewController(forKey: .to) as? BaseToastViewController { Log.debug("OK") // 可通过toastContentView访问公共视图逻辑 } else { Log.debug("NOT OK") }
方案2:使用非泛型协议
定义一个协议,让泛型ToastViewController遵守协议并实现公共接口:
// 定义非泛型协议 protocol ToastViewControllerProtocol: UIViewController { var toastContentView: ToastContentView? { get } } // 让泛型类遵守协议 class ToastViewController<ContentViewType: ToastContentView>: UIViewController, ToastViewControllerProtocol { var toastContentView: ToastContentView? { return view as? ContentViewType } }
转场时转换为协议类型:
if let toastVC = context.viewController(forKey: .to) as? ToastViewControllerProtocol { Log.debug("OK") } else { Log.debug("NOT OK") }
补充说明
如果需要处理泛型视图的具体逻辑,优先把公共逻辑封装在非泛型基类/协议中;若必须操作特定子类视图,可在获取基类/协议实例后,将toastContentView转换为对应子类类型(按需使用)。
内容的提问来源于stack exchange,提问作者Thomas Albert
相关产品推荐
相关产品推荐

