如何使用设置 MKMapView 仅放大一次?然后每次之后它应该只添加注释而不缩放
How can I use set up an MKMapView to only zoom in once? Then every time after it should just add annotations without zooming
我希望地图在打开时放大到伦敦的 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."
}
}
}
代码中存在一些不规范之处。
当您创建一个 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
}
}
}
在视图模型中,您可能想要这样做...
locations.append(contentsOf: [london, londonTwo, londonThree])
...而不是附加一个位置。
每次附加一个,都会触发一个新事件 (@Published
)。在您的场景中,您似乎想要触发两个事件:第一个事件针对伦敦地点,第二个事件针对柏林地点。
更新:我在 Github
上将我的建议作为 PR 添加到您的回购协议中
我希望地图在打开时放大到伦敦的 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."
}
}
}
代码中存在一些不规范之处。
当您创建一个
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
}
}
}
在视图模型中,您可能想要这样做...
locations.append(contentsOf: [london, londonTwo, londonThree])
...而不是附加一个位置。
每次附加一个,都会触发一个新事件 (
@Published
)。在您的场景中,您似乎想要触发两个事件:第一个事件针对伦敦地点,第二个事件针对柏林地点。
更新:我在 Github
上将我的建议作为 PR 添加到您的回购协议中