【问题标题】:Clustering annotation with swiftUI使用 swiftUI 进行聚类注释
【发布时间】:2021-08-29 17:12:09
【问题描述】:

我的目标是在地图上聚类注释并显示集群中的项目数,我没有 UIKit 经验并尽量避免它。是否可以仅使用 swiftUI 来完成?如果不是如何减少UIKit的干预? This is how it should look like

import SwiftUI
import MapKit

struct ContentView: View {

@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 43.64422936785126, longitude: 142.39329541313924),
    span: MKCoordinateSpan(latitudeDelta: 1.5, longitudeDelta: 2)
)

   var body: some View {
    Map(coordinateRegion: $region, annotationItems: data) { annotation in
        MapAnnotation(coordinate: annotation.coordinate) {
            Image(systemName: "person.circle.fill")
                .resizable()
                .frame(width: 20, height: 20)
                .foregroundColor(Color.purple)
        }
    }
    .edgesIgnoringSafeArea(.all)
   }
}

struct SampleData: Identifiable {
var id = UUID()
var latitude: Double
var longitude: Double
var coordinate: CLLocationCoordinate2D {
    CLLocationCoordinate2D(
        latitude: latitude,
        longitude: longitude)
 }
}

var data = [
SampleData(latitude: 43.70564024126748, longitude: 142.37968945214223),
SampleData(latitude: 43.81257464206404, longitude: 142.82112322464369),
SampleData(latitude: 43.38416585162576, longitude: 141.7252598737476),
SampleData(latitude: 45.29168643283501, longitude: 141.95286751470724),
SampleData(latitude: 45.49261392585982, longitude: 141.9343973160499),
SampleData(latitude: 44.69825427301145, longitude: 141.91227845284203)
]

struct ContentView_Previews: PreviewProvider {
 static var previews: some View {
    ContentView()
 }
}

【问题讨论】:

  • 你将不得不做一些grouping 与区域大小相关的CLLocation 有一个distance function
  • 我认为您可能必须回复 UIKit 组件才能实现这一目标
  • @loremipsum 你能更详细地描述一下如何做到这一点吗?
  • 你必须自己想出一个。我不认为有什么可做的。您使用当前区域跨度来决定该位置必须有多近才能对其进行聚类。我需要一些时间来创建一些东西来做这件事,而且 SO 不是一个代码编写服务。试一试,我们可以帮助微调。首先写下一个可能的过程。

标签: swiftui uikit


【解决方案1】:

我找到了使用 MapKit 对注释进行聚类的方法,但像视图一样重用地图以简化 swiftUI。好像是https://i.stack.imgur.com/u3hKR.jpg

import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {


var forDisplay = data
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 43.64422936785126, longitude: 142.39329541313924),
    span: MKCoordinateSpan(latitudeDelta: 1.5, longitudeDelta: 2)
)


class Coordinator: NSObject, MKMapViewDelegate {
    
    var parent: MapView

    init(_ parent: MapView) {
        self.parent = parent
    }
    
/// showing annotation on the map
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        guard let annotation = annotation as? LandmarkAnnotation else { return nil }
        return AnnotationView(annotation: annotation, reuseIdentifier: AnnotationView.ReuseID)
    }

}



func makeCoordinator() -> Coordinator {
    MapView.Coordinator(self)
}


func makeUIView(context: Context) -> MKMapView {
    ///  creating a map
    let view = MKMapView()
    /// connecting delegate with the map
    view.delegate = context.coordinator
    view.setRegion(region, animated: false)
    view.mapType = .standard
    
    for points in forDisplay {
        let annotation = LandmarkAnnotation(coordinate: points.coordinate)
        view.addAnnotation(annotation)
    }
    

    return view
    
}

func updateUIView(_ uiView: MKMapView, context: Context) {
    
}
}

struct SampleData: Identifiable {
var id = UUID()
var latitude: Double
var longitude: Double
var coordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
    latitude: latitude,
    longitude: longitude)
 }
}

var data = [
SampleData(latitude: 43.70564024126748, longitude: 142.37968945214223),
SampleData(latitude: 43.81257464206404, longitude: 142.82112322464369),
SampleData(latitude: 43.38416585162576, longitude: 141.7252598737476),
SampleData(latitude: 45.29168643283501, longitude: 141.95286751470724),
SampleData(latitude: 45.49261392585982, longitude: 141.9343973160499),
SampleData(latitude: 44.69825427301145, longitude: 141.91227845284203)
]


class LandmarkAnnotation: NSObject, MKAnnotation {
let coordinate: CLLocationCoordinate2D
init(
     coordinate: CLLocationCoordinate2D
) {
    self.coordinate = coordinate
    super.init()
}
}


/// here posible to customize annotation view
let clusterID = "clustering"

class AnnotationView: MKMarkerAnnotationView {

static let ReuseID = "cultureAnnotation"

/// setting the key for clustering annotations
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
    clusteringIdentifier = clusterID
}


required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func prepareForDisplay() {
    super.prepareForDisplay()
    displayPriority = .defaultLow
 }
}

并像使用默认视图一样使用该地图

import SwiftUI

struct ContentView: View {


var body: some View {
MapView()
    .edgesIgnoringSafeArea(.all)
 }
}

为了解决一个问题,我使用了下一个资源:

https://www.hackingwithswift.com/books/ios-swiftui/communicating-with-a-mapkit-coordinator

https://www.hackingwithswift.com/books/ios-swiftui/advanced-mkmapview-with-swiftui

https://developer.apple.com/videos/play/wwdc2017/237/

https://www.youtube.com/watch?v=QuYA7gQjTt4

【讨论】:

  • 很好的答案!不知道为什么 0 票。
猜你喜欢
  • 1970-01-01
  • 2022-01-19
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-30
相关资源
最近更新 更多