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

如何正确使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:54:05