如何在 Swift UI 中初始化 State Var 而不会出现错误 "Cannot use instance member 'XXX' within property initializer;"

How can I initialize a State Var in Swift UI without getting the error "Cannot use instance member 'XXX' within property initializer;"

我希望将用户位置放在 MapView 上,并在用户移动时更新位置。我正在为 class 处理位置管理器内容使用 @observedObject Var,为 MKCoordinateRegion() Class 使用 @state Var。但是我 运行 遇到一个问题,如果我在声明和定义 @state var 之前放置 @observedObject var 的声明,我会遇到错误

("不能在 属性 初始化器中使用实例成员 'latitude';在 'self' 可用之前 属性 初始化器 运行")

我已经看到其他人 post 这个问题,我尝试了 .init() 函数以及使用惰性变量。然而问题来了,@state var 需要是 MKCoordinateRegion() 类型,因此需要用值初始化。我不理解如何解决这个问题的根源很可能是不理解视图加载的时间表,因为我只使用过 UIBuilder 而不是 SwiftUI。如有任何帮助,我们将不胜感激!

struct MapView: View {
    @ObservedObject var usersLocation = LocationManager()
    var latitude: Double{ return((usersLocation.location?.coordinate.latitude ?? 0))}
    var longitude: Double{ return((usersLocation.location?.coordinate.longitude ?? 0))}
    @State var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: latitude , longitude: longitude),
        span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
    )
    var body: some View {
        Map(coordinateRegion: $region)
            .onAppear()
        Text(String(latitude));
    }
    
}

问题是属性的值相互依赖,你不能这样声明它们。

但是你可以实现一个init方法

struct MapView: View {
    @ObservedObject var usersLocation : LocationManager
    var latitude: Double
    var longitude: Double
    @State var region : MKCoordinateRegion

    init(manager : LocationManager) {
        self.usersLocation = manager
        let lat = manager.location?.coordinate.latitude ?? 0
        self.latitude = lat
        let long = manager.location?.coordinate.latitude ?? 0
        self.longitude = long
        let reg = MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: lat , longitude: long),
            span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
        )
        self._region = State<MKCoordinateRegion>(initialValue: reg)
    }

    var body: some View {
        Map(coordinateRegion: $region)
            .onAppear()
        Text(String(latitude));
    }
    
}

并在父视图中传递 LocationManager 并将其声明为 @StateObject

@StateObject var locationManager = LocationManager()
...
MapView(manager: locationManager)

你也可以这样使用:

struct MapView: View {
    @ObservedObject var usersLocation = LocationManager()
    @State var latitude: Double = 0.0
    @State var longitude: Double = 0.0
    @State var region = MKCoordinateRegion()
    
    var body: some View {
        Map(coordinateRegion: $region)
            .onAppear {
                latitude = (usersLocation.location?.coordinate.latitude ?? 0.0)
                longitude = (usersLocation.location?.coordinate.longitude ?? 0.0)
                region = MKCoordinateRegion(
                    center: CLLocationCoordinate2D(latitude: latitude , longitude: longitude),
                    span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
            }
    }
}