从UIKit迁移到SwiftUI:如何兼顾BaseViewController继承?
解决SwiftUI迁移中保留BaseViewController特性的方案
由于Swift不支持多继承,无法让一个类同时继承BaseViewController和UIHostingController,可以通过以下两种方案保留Base的特性:
方法一:修改BaseViewController的继承链
如果BaseViewController仅被需要迁移到SwiftUI的页面使用,或者可以调整其继承关系,直接让BaseViewController继承UIHostingController,后续子类继承BaseViewController即可同时拥有两者的能力。
// 调整BaseViewController的继承关系 class BaseViewController: UIHostingController<AnyView> { // 保留原BaseViewController的所有通用逻辑 init(rootView: AnyView) { super.init(rootView: rootView) setupBaseConfigurations() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupBaseConfigurations() { // 原Base中的通用设置,比如导航栏样式、状态栏配置等 navigationItem.backButtonTitle = "" navigationController?.navigationBar.barTintColor = .white } // 原Base中的通用方法,比如弹窗提示、加载状态控制 func showToast(message: String) { // 实现逻辑 } } // 目标视图控制器继承调整后的BaseViewController class CountryLanguageViewController: BaseViewController { init() { let swiftUIView = SelectCountrySwiftUIView() super.init(rootView: AnyView(swiftUIView)) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() // 直接调用Base中的通用方法 showToast(message: "加载完成") } }
方法二:用协议+扩展抽离Base的通用逻辑
如果无法修改BaseViewController的继承关系(比如它还被其他纯UIKit页面依赖),可以把Base中的通用功能抽成协议,通过协议扩展实现默认逻辑,让UIHostingController子类遵守协议复用功能。
// 定义协议封装Base的通用能力 protocol BaseCompatible: UIViewController { func setupBaseNavigation() func showLoading() func hideLoading() } // 协议扩展实现默认逻辑,复用原Base的代码 extension BaseCompatible { func setupBaseNavigation() { navigationItem.backButtonTitle = "" navigationController?.navigationBar.tintColor = .darkGray } func showLoading() { let indicator = UIActivityIndicatorView(style: .large) indicator.center = view.center view.addSubview(indicator) indicator.startAnimating() } func hideLoading() { view.subviews.first(where: { $0 is UIActivityIndicatorView })?.removeFromSuperview() } } // 目标控制器继承UIHostingController并遵守协议 class CountryLanguageViewController: UIHostingController<SelectCountrySwiftUIView>, BaseCompatible { init() { super.init(rootView: SelectCountrySwiftUIView()) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() // 调用协议中的通用方法 setupBaseNavigation() } }
如果BaseViewController有存储属性(比如用户信息、全局配置),可以通过单例、依赖注入的方式在目标控制器中引入,或者在协议中定义关联类型来处理属性需求。
内容的提问来源于stack exchange,提问作者Krutika Sonawala
相关产品推荐
相关产品推荐

