我的应用程序请求JSON数据(纬度、经度和关于一个地方的其他信息),然后以可点击注释的形式在地图上显示这些数据。我收到了大约3万份,所以正如你所能想象的,这个应用程序可能会有一点“滞后”。
我认为最适合应用程序的解决方案是,只在一定的缩放级别上显示这些注释(例如,当用户缩放时,只有一个城市一次可见,注释就会显示出来)。因为有很多,显示所有的3万可能会崩溃的应用程序,这也是为什么我也希望只显示那些接近用户放大的地方。
下面的代码立即显示所有注解同时在所有缩放级别。有没有办法让它适应到我上面描述的事情呢?
struct Map: UIViewRepresentable {
@EnvironmentObject var model: ContentModel
@ObservedObject var data = FetchData()
var locations:[MKPointAnnotation] {
var annotations = [MKPointAnnotation]()
// Loop through all places
for place in data.dataList {
// If the place does have lat and long, create an annotation
if let lat = place.latitude, let long = place.longitude {
// Create an annotation
let a = MKPointAnnotation()
a.coordinate = CLLocationCoordinate2D(latitude: Double(lat)!, longitude: Double(long)!)
a.title = place.address ?? ""
annotations.append(a)
}
}
return annotations
}
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
// Show user on the map
mapView.showsUserLocation = true
mapView.userTrackingMode = .followWithHeading
return mapView
}
func updateUIView(_ uiView: MKMapView, context: Context) {
// Remove all annotations
uiView.removeAnnotations(uiView.annotations)
// HERE'S WHERE I SHOW THE ANNOTATIONS
uiView.showAnnotations(self.locations, animated: true)
}
static func dismantleUIView(_ uiView: MKMapView, coordinator: ()) {
uiView.removeAnnotations(uiView.annotations)
}
// MARK: Coordinator Class
func makeCoordinator() -> Coordinator {
return Coordinator(map: self)
}
class Coordinator: NSObject, MKMapViewDelegate {
var map: Map
init(map: Map) {
self.map = map
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't treat user as an annotation
if annotation is MKUserLocation {
return nil
}
// Check for reusable annotations
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: Constants.annotationReusedId)
// If none found, create a new one
if annotationView == nil {
annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: Constants.annotationReusedId)
annotationView!.canShowCallout = true
annotationView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
} else {
// Carry on with reusable annotation
annotationView!.annotation = annotation
}
return annotationView
}
}
}
寻找答案已经有一段时间了,但没有找到任何有效的答案。我想有一种方法可以让地图重新显示,然后在map中给出条件,但是不知道怎么做。谢谢你读了这么多!
发布于 2022-09-03 11:07:31
您的委托可以实现mapView(_:regionDidChangeAnimated:)
,以便在用户完成更改映射的可见区域的手势时得到通知。它可以在手势发生时实现要通知的。
您可以通过询问映射的region
属性来获取它的可见区域。关于缩放级别,region
文档说:
该区域包括地图中心所在的纬度和经度点,以及要显示的坐标范围。span值为映射提供隐式缩放值。显示区域越大,缩放的量就越小。同样,显示区域越小,缩放的量就越大。
updateUIView
方法每次调用locations
数组时都会重新计算它(因为locations
是一个计算属性)。您应该检查SwiftUI调用updateUIView
的频率,并决定是否需要缓存locations
数组。
如果要有效地查找可见区域中的位置,请尝试将这些位置存储在四叉树中。
发布于 2022-11-23 11:13:23
终于发现了.
Coordinator
类可以实现mapView(_:regionDidChangeAnimated:)
(如@rob所说),在用户完成更改地图可见区域的手势后调用它。当发生这种情况时,将更新映射及其数组上的注释。看起来像这样..。
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if mapView.region.span.latitudeDelta < <Double that represents zoom> && mapView.region.span.longitudeDelta < <Double that represents zoom> {
mapView.removeAnnotations(mapView.annotations)
mapView.addAnnotations(map.getLocations(center: mapView.region.center))
}
}
..。< >
中的短语( if语句中缺少的双倍)将被替换为您自己的代码(双倍越大,查看注释所需的缩放就越小)。注释数组由Map
结构中定义的函数更新,如下所示.
func getLocations(center: CLLocationCoordinate2D) -> [MKPointAnnotation] {
var annotations = [MKPointAnnotation]()
let annotationSpanIndex: Double = model.latlongDelta * 10 * 0.035
// Loop through all places
for place in data.dataList {
// If the place does have lat and long, create an annotation
if let lat = place.latitude, let long = place.longitude {
// Create annotations only for places within a certain region
if Double(lat)! >= center.latitude - annotationSpanIndex && Double(lat)! <= center.latitude + annotationSpanIndex && Double(long)! >= center.longitude - annotationSpanIndex && Double(long)! <= center.longitude + annotationSpanIndex {
// Create an annotation
let a = MKPointAnnotation()
a.coordinate = CLLocationCoordinate2D(latitude: Double(lat)!, longitude: Double(long)!)
a.title = place.adresa ?? ""
annotations.append(a)
}
}
}
return annotations
}
..。其中,annotationSpanIndex
决定中心点周围区域的大小将显示注释(索引越大,区域越大)。理想情况下,这个区域应该略大于显示注释的缩放范围。
https://stackoverflow.com/questions/73594617
复制相似问题