SwiftUI:在视图更新中发布更改是不允许的,这会导致未定义的行为(当使用“ViewModel”方法时)。

21

我已经阅读了许多关于这个错误的问题,大多与解散表格有关,但没有一个涉及SwiftUI的Map。下面的代码生成了这个错误。视图模型中没有更新任何内容,我只是将一个绑定传递给Map初始化器中的region。对于region使用本地状态变量可以正常工作而没有错误。我正在运行Xcode 14.0。如果我删除@Published属性包装器,则错误消失。所以我不确定视图模型应该如何通知视图区域已经发生了更改,可能是由于位置更新。

import SwiftUI
import MapKit

class MM : ObservableObject {
    @Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
}

struct SimpleMap: View {
    @ObservedObject var mm = MM()
    @State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))

    var body: some View {
        //Error
        Map(coordinateRegion: $mm.region)
        
        //No Error
        //Map(coordinateRegion: $region)
    }
}


6
使用StateObject替代ObservedObject - undefined
1
ObservableObject object initialised with @StateObject and when you pass it to other views, in those views you need to declare it with @ObservedObject - undefined
1
@StateObject一点也不改变事情。从iOS16和Swift 4开始,具有Published属性的ObservableObjects不允许进行引用绑定。您需要使用一个@State属性,而且永远不要手动操作它。 - undefined
1
@Vyacheslav 我已经转而使用 MKMapView。Swift UI 的地图太过有限,可能只适用于简单的应用程序。 - undefined
1
哦,非常抱歉,我忽略了你的问题。我当时的回答有些嘲讽了。2022年10月份,Xcode出现了一个很烦人的循环引用问题,让我非常苦恼。唯一的解决方法就是要么使用@State,并且永远不手动编写任何东西(讽刺的是无用的!),要么选择使用UIKit版本的MapKit并将其包装成ViewRepresentable。我选择了后者。在Xcode 14.2中,这个所谓的bug似乎大部分已经解决了。也许SwiftUI MapKit版本现在可以使用了? - undefined
显示剩余6条评论
1个回答

0
你需要在ViewModel中添加@MainActor属性,并将@ObervedObject替换为@StateObject
以下是一个实现的示例:
import SwiftUI
import MapKit

struct SimpleMap: View {
    @StateObject var vm = VM()

    var body: some View {
        Map(coordinateRegion: $vm.region)
    }
}

extension SimpleMap {
    @MainActor class VM: ObservableObject {
        @Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
    }
}

这里最重要的是@MainActor属性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接