如何通过 Binding 和 ObservedObject 更新 UIViewRepresentable 地图

Posted

技术标签:

【中文标题】如何通过 Binding 和 ObservedObject 更新 UIViewRepresentable 地图【英文标题】:How to update UIViewRepresentable map through Binding and ObservedObject 【发布时间】:2019-11-06 08:46:19 【问题描述】:

我有这个简单的 MapView,我有一个 ObservedObject 数据源要更新,但它不起作用。

这是内容视图:

struct ContentView: View 
    @ObservedObject var trackingOnMapViewModel = TrackingOnMapViewModel()

    var body: some View 
        ZStack 
            MapView(selectedRegion: $trackingOnMapViewModel.selectedRegion)
                .edgesIgnoringSafeArea(.vertical)
            VStack 
                Spacer()
                Button(action: 
                    self.trackingOnMapViewModel.selectNextRegion()
                ) 
                    Text("Next")
                        .padding()
                
            
        
    

这是一个简单的地图视图:

struct MapView: UIViewRepresentable 
    @Binding var selectedRegion: MKCoordinateRegion

    func makeUIView(context: Context) -> MKMapView 
        print("MapView - makeUIView")
        let map = MKMapView()
        return map
    

    func updateUIView(_ mapView: MKMapView, context: Context) 
        print("MapView - updateUIView")
        mapView.setRegion(selectedRegion, animated: true)
    

这是数据源:

class TrackingOnMapViewModel: ObservableObject 

    var regions: [MKCoordinateRegion] = [
        MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 10.0, longitude: 10.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)),
        MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 20.0, longitude: 20.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)),
        MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 30.0, longitude: 30.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)),
        MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 40.0, longitude: 40.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0))
    ]

    var selectedRegion: MKCoordinateRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0))

    var currentIndex = 0


    func selectNextRegion() 
        print("TrackingOnMapViewModel - selectNextLandmark")
        currentIndex = currentIndex < regions.count-1 ? currentIndex + 1 : 0
        self.selectedRegion = regions[currentIndex]
        print("selectedRegion - \(selectedRegion)")
    

在这种情况下,地图不会更新。

如果我把逻辑放到没有 ObservedObject 的 ContentView 中:

struct ContentView: View 
//    @ObservedObject var trackingOnMapViewModel = TrackingOnMapViewModel()

@State var regions: [MKCoordinateRegion] = [
    MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 10.0, longitude: 10.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)),
    MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 20.0, longitude: 20.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)),
    MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 30.0, longitude: 30.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)),
    MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 40.0, longitude: 40.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0))
]

@State var selectedRegion: MKCoordinateRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0), span: MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0))

@State var currentIndex = 0

var body: some View 
    ZStack 
        MapView(selectedRegion: $selectedRegion)
            .edgesIgnoringSafeArea(.vertical)
        VStack 
            Spacer()
            Button(action: 
                self.selectNextRegion()
            ) 
                Text("Next")
                    .padding()
            
        
    


private func selectNextRegion() 
    print("ContentView - selectNextLandmark")
    currentIndex = currentIndex < regions.count-1 ? currentIndex + 1 : 0
    self.selectedRegion = regions[currentIndex]

那么地图正在更新。

你能帮我解决这个问题吗?

【问题讨论】:

【参考方案1】:

在我发布问题的那一刻,我发现了问题。 我忘记在 TrackingOnMapViewModel 中将 selectedRegion 变量标记为 @Published。

@Published var selectedRegion: MKCoordinateRegion = MKCoordinateRegion

【讨论】:

以上是关于如何通过 Binding 和 ObservedObject 更新 UIViewRepresentable 地图的主要内容,如果未能解决你的问题,请参考以下文章

绑定: 通过 Binding 绑定对象, 通过 x:Bind 绑定对象, 通过 Binding 绑定集合, 通过 x:Bind 绑定集合

通过 ngModel Binding 设置值时如何在 textarea 上触发更改事件

如何在 SwiftUI 中使用 inout 而不是 Binding?

使用 Rails.cache 时 Rspec 测试失败,但如果我执行 binding.pry 则通过

Symfony messenger 和 mailer:如何添加 binding_key?

如何使用 Binding="Binding" 以编程方式创建 DataTrigger?