能否在MKMapView的Coordinator中使用ObservedObject管理视图状态?
问题分析与解决方案:在MapCoordinator中共享HomeState实例
你遇到的问题核心很明确:MapCoordinator和HomeView各自创建了独立的HomeState实例,这俩完全是不同的对象。所以当Coordinator里调用setUserLocated时,更新的是它自己手里的那个HomeState的userLocated属性,而HomeView监听的是另一个完全无关的实例,视图自然不会触发刷新。
下面是具体的修复步骤,帮你实现状态的共享:
1. 让HomeState成为共享实例
我们需要让MapCoordinator和HomeView使用同一个HomeState对象,而不是各自新建。
修改HomeView,改为依赖注入模式
把HomeView里硬初始化的HomeState改成外部传入的方式,这样可以保证整个链路用的是同一个实例:
struct HomeView: View { @ObservedObject var homeState: HomeState // 不再内部初始化,由外部传入 var body: some View { ZStack(alignment: .bottom) { MapView(homeState: homeState) // 把共享的homeState传给MapView if homeState.userLocated { Circle() .frame(width: 60, height: 60) .foregroundColor(.green) } } } }
修改MapView,传递HomeState给Coordinator
MapView需要接收外部传入的HomeState,并在创建Coordinator的时候把这个实例传进去:
struct MapView: UIViewRepresentable { let homeState: HomeState func makeUIView(context: Context) -> MKMapView { let mapView = MKMapView() mapView.delegate = context.coordinator mapView.showsUserLocation = true return mapView } func updateUIView(_ uiView: MKMapView, context: Context) {} func makeCoordinator() -> MapCoordinator { MapCoordinator(homeState: homeState) // 把共享实例传给Coordinator } }
修改MapCoordinator,通过初始化接收HomeState
最后修改Coordinator,去掉内部初始化的HomeState,改为通过构造方法接收外部传入的实例:
final class MapCoordinator: NSObject, MKMapViewDelegate { let homeState: HomeState // 用let保存共享实例,不需要@ObservedObject init(homeState: HomeState) { self.homeState = homeState super.init() } func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) { self.homeState.setUserLocated(true) } }
2. 初始化共享实例并注入到HomeView
在你的App入口或者父视图中,创建唯一的HomeState实例,然后传给HomeView:
@main struct YourApp: App { let homeState = HomeState() // 这里创建全局唯一的实例 var body: some Scene { WindowGroup { HomeView(homeState: homeState) } } }
额外优化:用环境对象简化传递
如果你的HomeState需要在多个视图间共享,还可以用@EnvironmentObject来简化传递,不用手动在每个视图里传参:
// 在App入口设置环境对象 @main struct YourApp: App { @StateObject private var homeState = HomeState() var body: some Scene { WindowGroup { HomeView() .environmentObject(homeState) } } } // HomeView里直接用环境对象 struct HomeView: View { @EnvironmentObject var homeState: HomeState var body: some View { ZStack(alignment: .bottom) { MapView() if homeState.userLocated { Circle() .frame(width: 60, height: 60) .foregroundColor(.green) } } } } // MapView里获取环境对象传给Coordinator struct MapView: UIViewRepresentable { @EnvironmentObject var homeState: HomeState func makeUIView(context: Context) -> MKMapView { let mapView = MKMapView() mapView.delegate = context.coordinator mapView.showsUserLocation = true return mapView } func updateUIView(_ uiView: MKMapView, context: Context) {} func makeCoordinator() -> MapCoordinator { MapCoordinator(homeState: homeState) } }
这样修改后,Coordinator和HomeView就共享同一个HomeState实例了,当Coordinator调用setUserLocated时,HomeView里的userLocated会实时更新,Circle也会正常显示出来。
内容的提问来源于stack exchange,提问作者user1354934
相关产品推荐
相关产品推荐

