如何正确使用init解决SwiftUI中属性初始化器在self可用前运行的错误
问题原因
- 你声明的
annotations是存储属性,Swift中类/结构体的存储属性初始化逻辑会在self完全初始化完成前执行,此时还无法访问实例成员connectivity,所以出现第一个报错。 - 因为SwiftUI的
View是不可变值类型,lazy属性的读取会触发self的修改,在不可变的View上下文中访问就会触发第二个"self is immutable"报错。 - 额外注意:即使你绕过了初始化报错,存储属性只会读取一次
connectivity的初始坐标,后续手表推送新坐标时注记也不会自动更新,不符合功能需求。
可行解决方案
方案1:改为计算属性(最简便,适合你的场景)
直接将annotations改成计算属性,每次读取时实时拉取connectivity的最新坐标,同时connectivity是@StateObject,它的@Published属性更新时会触发View重绘,自动更新注记坐标:
// 替换原来的annotations存储属性声明 var annotations: [Place] { [ Place(name: "Apple Watch", coordinate: CLLocationCoordinate2D(latitude: connectivity.receivedLat, longitude: connectivity.receivedLong)) ] }
如果要避免初始状态下(0,0)坐标的无效注记,可以加判断过滤:
var annotations: [Place] { // 排除未收到有效坐标的初始状态 guard connectivity.receivedLat != 0, connectivity.receivedLong != 0 else { return [] } return [ Place(name: "Apple Watch", coordinate: CLLocationCoordinate2D(latitude: connectivity.receivedLat, longitude: connectivity.receivedLong)) ] }
方案2:用@State + onReceive监听更新(适合多注记管理场景)
如果后续需要管理多个不同来源的注记,可以把annotations声明为@State属性,监听connectivity的坐标变化主动更新:
// 声明@State注解的空数组 @State private var annotations: [Place] = []
然后在body的Map组件上添加监听回调:
Map(coordinateRegion: $viewModel.region, showsUserLocation: true) .ignoresSafeArea() .accentColor(Color(.systemPink)) // 监听坐标更新,修改注记数组 .onReceive(connectivity.$receivedLat) { _ in guard connectivity.receivedLat != 0, connectivity.receivedLong != 0 else { annotations = [] return } annotations = [ Place(name: "Apple Watch", coordinate: CLLocationCoordinate2D(latitude: connectivity.receivedLat, longitude: connectivity.receivedLong)) ] }
内容的提问来源于stack exchange,提问作者René Tarot
相关产品推荐
相关产品推荐

