微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用设置 MKMapView 只放大一次?然后每次之后它应该只添加注释而不缩放

如何解决如何使用设置 MKMapView 只放大一次?然后每次之后它应该只添加注释而不缩放

我希望地图打开时放大到伦敦的 3 个地点。然后 7 秒后,我希望柏林位置显示在地图上,但我不希望地图放大到它们。我希望用户在整个时间内都可以滚动地图而不会“跳到”任何地方。我猜这可能是我对 SwiftUI 工作原理的理解的一个问题。但我不明白怎么做。这是一些代码显示了我想要实现的目标。或者您可以在此处获取工作示例 -> https://github.com/cameronhenige/TestSwiftUIMapZoom。在当前状态下,它会放大到伦敦的位置,然后在 7 秒后放大到伦敦和柏林的位置。


import SwiftUI
import MapKit

struct ContentView: View {
    
    @Observedobject var testviewmodel = Testviewmodel()
    @State var map = MKMapView()

    var SearchingButtonText: some View {
            return Text("Test" )
    }
    
    var body: some View {
            vstack {
            
                TestMapView(map: self.$map,locations: $testviewmodel.locations)
                
            }.onAppear() {
                self.testviewmodel.fetchData()
              }
    }
}



import Foundation
import CoreLocation
import MapKit

class Testviewmodel: NSObject,ObservableObject {
    
    @Published var locations: [MKPointAnnotation] = []
    
    func fetchData() {
        
        let london = MKPointAnnotation()
        london.title = "London"
        london.coordinate = CLLocationCoordinate2D(latitude: 51.507222,longitude: -0.1275)
        
        let londonTwo = MKPointAnnotation()
        londonTwo.title = "London Two"
        londonTwo.coordinate = CLLocationCoordinate2D(latitude: 51.507224,longitude: -0.1277)
        
        
        let londonThree = MKPointAnnotation()
        londonThree.title = "London Three"
        londonThree.coordinate = CLLocationCoordinate2D(latitude: 51.507226,longitude: -0.1279)
        

        let berlin = MKPointAnnotation()
        berlin.title = "Berlin"
        berlin.coordinate = CLLocationCoordinate2D(latitude: 52.5200,longitude: 13.4050)
        
        let berlinTwo = MKPointAnnotation()
        berlinTwo.title = "Berlin Two"
        berlinTwo.coordinate = CLLocationCoordinate2D(latitude: 52.5202,longitude: 13.4052)
        
        
        let berlinThree = MKPointAnnotation()
        berlinThree.title = "Berlin Three"
        berlinThree.coordinate = CLLocationCoordinate2D(latitude: 52.5204,longitude: 13.4056)
        
    
        
        locations.append(london)
        locations.append(londonTwo)
        locations.append(londonThree)
        //These should initially zoom in.
        
        let seconds = 7.0
        dispatchQueue.main.asyncAfter(deadline: .Now() + seconds) {
            self.locations.append(berlin)
            self.locations.append(berlinTwo)
            self.locations.append(berlinThree)
            //These should just appear on the map but not pan the map to show them.
        }

    }
    
    
}


import SwiftUI
import MapKit

struct TestMapView: UIViewRepresentable {
    
    @Binding var map : MKMapView
    @Binding var locations: [MKPointAnnotation]
    @State var hasZoomed = false
    
    func makeUIView(context: Context) -> MKMapView {
        return map
    }
    
    func updateUIView(_ view: MKMapView,context: Context) {
        self.map.addAnnotations(locations)
        
        //I only want to call this once.
        if(!hasZoomed && !self.locations.isEmpty) {
            self.map.showAnnotations(locations,animated: false)
            hasZoomed = true //here i get a warning "Modifying state during view update,this will cause undefined behavior."
        }
    }
}

解决方法

代码中存在一些违规行为。

  1. 当您创建 UIViewRepresentable 视图时,该结构负责 UIKit 视图分配/更新。

    地图创建为 @State 并传入,我认为这不是正确的做法。

你可以尝试这样的事情:

struct TestMapView: UIViewRepresentable {

    final class Coordinator {
        var hasZoomed = false
    }
    
    @Binding var locations: [MKPointAnnotation]

    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
    
    func makeUIView(context: Context) -> MKMapView {
        return MKMapView(frame: .zero)
    }
    
    func updateUIView(_ view: MKMapView,context: Context) {
        view.removeAnnotations(view.annotations)
        view.addAnnotations(locations)
        if(!context.coordinator.hasZoomed && !self.locations.isEmpty) {
            view.showAnnotations(locations,animated: false)
            context.coordinator.hasZoomed = true
        }
    }
}
  1. 在视图模型中,你可能想要这样做...

    locations.append(contentsOf: [london,londonTwo,londonThree])

    ...而不是附加单个位置。

    每次追加一个事件时,都会触发一个新事件 (@Published)。在您的场景中,您似乎想要触发两个事件:第一个用于伦敦地点,第二个用于柏林。

更新:我将我的建议作为 PR 添加到您在 Github 上的存储库

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。