如何从UIKit侧更新SwiftUI的@State变量以触发NavigationLink跳转
问题根源
你直接修改UIHostingController.rootView的@State属性不会生效,原因有两个:
@State是SwiftUI为视图内部私有状态设计的属性包装器,其存储由SwiftUI框架内部维护,不属于结构体本身的可直接修改的存储属性- SwiftUI的视图是值类型,你从
UIHostingController拿到的rootView是原视图的拷贝,修改拷贝的属性不会影响已经渲染的视图实例,也无法触发视图重绘
解决方案
采用ObservableObject作为跨UIKit和SwiftUI的共享状态载体,步骤如下:
- 定义可观察状态类
class DateOptionsState: ObservableObject { @Published var selectedItem: AppMainFeatureData? = nil }
- 修改
DateOptions视图,替换内部@State为观察这个共享状态
public struct DateOptions: View, MiscellaneousHelper { // iOS14及以上用@StateObject,低版本兼容用@ObservedObject @StateObject var state: DateOptionsState let tabBarController: TabBarController public var body: some View { NavigationView { List(AppMainFeatureData.dateItems, id: \.self) { item in // 绑定改为绑定state的selectedItem NavigationLink(destination: DateFeatureController(svc: tabBarController.svc, feature: item), tag: item, selection: $state.selectedItem) { ImageText(text: item.title, imageName: item.iconName) } } .navigationBarTitle(SideBarSection.dates.title) } } }
- 在你的
TabBarController中持有这个状态类的实例,创建视图时注入
// TabBarController类中新增属性持有状态实例 private let dateOptionsState = DateOptionsState() // 创建UIHostingController时传入状态 let dateView = DateOptions(state: dateOptionsState, tabBarController: self) let dateViewController = UIHostingController(rootView: dateView) dateViewController.tabBarItem = tabBarItem viewControllers?.insert(dateViewController, at: 1)
- 需要触发跳转时,直接修改你持有的状态实例的属性即可
// 不需要再获取rootView修改,直接改持有的state dateOptionsState.selectedItem = .dateAddSubtract dPrint("After \(dateOptionsState.selectedItem)")
修改后@Published修饰的属性变化会自动通知SwiftUI视图更新,触发NavigationLink的跳转逻辑,和用户手动点击的效果完全一致。
内容的提问来源于stack exchange,提问作者Phantom59
相关产品推荐
相关产品推荐

