You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

尝试从子视图修改@EnvironmentObject失败:对象为只读属性

问题分析与解决方案

你遇到的错误Cannot assign to property: 'currentPosition' is a get-only property有两个核心原因:

1. @EnvironmentObject是只读的,不能直接替换实例

@EnvironmentObject这个属性包装器的设计是让你读取共享的ObservableObject实例,而不是直接给它赋值一个新的实例。它的wrappedValue是只读的,所以你不能写currentPosition = CurrentPosition(...)这种代码。

2. Coordinator不能使用@EnvironmentObject

你的Coordinator是NSObject的子类,并不是SwiftUI View,所以@EnvironmentObject属性包装器在它里面是无效的——SwiftUI不会自动给非View的类注入环境对象,这个属性实际上不会被正确初始化。


正确的解决方案

我们需要做两个关键修改:

第一步:给Coordinator传递CurrentPosition实例

在MapView的makeCoordinator()方法里,把当前的currentPosition实例传递给Coordinator,让它持有引用:

第二步:直接更新CurrentPosition的已发布属性

不需要创建新的CurrentPosition实例,直接修改现有实例的northEast和southWest属性——因为它们被@Published标记,属性变化会自动通知所有订阅的视图。

修改后的完整MapView代码如下:

struct MapView: UIViewRepresentable {
    @Binding var weatherStations: [WeatherStation]
    @Binding var selectedWeatherStation: WeatherStation?
    @EnvironmentObject var currentPosition: CurrentPosition
    
    final class Coordinator: NSObject, MKMapViewDelegate {
        // 持有CurrentPosition的引用
        private let currentPosition: CurrentPosition
        
        // 通过初始化传入实例
        init(currentPosition: CurrentPosition) {
            self.currentPosition = currentPosition
        }
        
        func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
            // 直接更新已发布属性,而非替换整个实例
            currentPosition.northEast = mapView.northEastCoordinate
            currentPosition.southWest = mapView.southWestCoordinate
        }
    }
    
    // 创建Coordinator时传入currentPosition
    func makeCoordinator() -> Coordinator {
        Coordinator(currentPosition: currentPosition)
    }
    
    // 实现makeUIView和updateUIView(你的原有逻辑保留)
    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        // 其他地图初始化设置...
        return mapView
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {
        // 地图更新逻辑...
    }
}

为什么这样能解决问题?

  • 你的CurrentPosition是ObservableObject,带有@Published属性,修改这些属性会自动触发所有依赖它的视图更新,完全满足你"移动地图时更新坐标,用于API请求"的需求。
  • 通过初始化传递的方式给Coordinator提供CurrentPosition实例,避开了非View类无法使用@EnvironmentObject的问题,让Coordinator能正确修改共享状态。

内容的提问来源于stack exchange,提问作者trusk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:02:32