点击收集视图单元以向地图添加注释

问题描述 投票:1回答:1

现在,我有一个地图和一个显示该地图图标的集合视图。我要这样做,以便在选择其中一个图标时在地图上该特定类别内显示那些不同的位置;类似于Apple Maps。

这是我的集合视图代码。

class ContentViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

let imageArray = [UIImage(named: "1"), UIImage(named: "2"), UIImage(named: "3")]
let imageNameArray = ["Image 1", "Image 2", "Image 3"]

override func viewDidLoad() {
    super.viewDidLoad()

}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return imageArray.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
    cell.mapIconImage.image = imageArray[indexPath.row]
    cell.mapIconLabel.text! = imageNameArray[indexPath.row]

class CustomCell: UICollectionViewCell {

@IBOutlet weak var mapIconImage: UIImageView!
@IBOutlet weak var mapIconLabel: UILabel!

}

这是我的地图视图的代码。

struct PlacesOnMap {
var name: String
var latitude: Double
var longitude: Double

init(name: String, latitude: Double, longitude: Double) {
    self.name = name
    self.latitude = latitude
    self.longitude = longitude
}
}

class MapViewController: UIViewController {

@IBOutlet var mapView: MKMapView!

var locationManager = CLLocationManager()
var currentCoordinate: CLLocationCoordinate2D!

var places = [PlacesOnMap(name: "place 1", latitude: 28.551700, longitude: -81.374800),
    PlacesOnMap(name: "place 2", latitude: 28.553018, longitude: -81.374206),
    PlacesOnMap(name: "place 3", latitude: 28.553019, longitude: -81.367839)
    ]
var buildings = [PlacesOnMap(name: "place 1", latitude: 28.556969, longitude: -81.364319),
    PlacesOnMap(name: "place 2", latitude: 28.558126, longitude: -81.364725)
    ]
var recreation = [PlacesOnMap(name: "place 1", latitude: 28.54693, longitude: -81.393071),
    PlacesOnMap(name: "place 2", latitude: 28.538523, longitude: -81.385399),
    PlacesOnMap(name: "place 3", latitude: 28.542817, longitude: -81.378117),
    PlacesOnMap(name: "place 4", latitude: 28.538985, longitude: -81.404694)
]

override func viewDidLoad() {
    super.viewDidLoad()

    locationManager.requestWhenInUseAuthorization()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
    locationManager.startUpdatingLocation()
}

func setPlacesAnnotations() {
    let places = placesOfWorship.map { placeOnMap -> MKPointAnnotation in
        let place = MKPointAnnotation()
        place.coordinate =  CLLocationCoordinate2D(latitude: placeOnMap.latitude, longitude: placeOnMap.longitude)
        place.title = placeOnMap.name
        return place
    }
    mapView.addAnnotations(places)
}

func setBuildingsAnnotations() {
    let places = organizations.map { placeOnMap -> MKPointAnnotation in
        let place = MKPointAnnotation()
        place.coordinate =  CLLocationCoordinate2D(latitude: placeOnMap.latitude, longitude: placeOnMap.longitude)
        place.title = placeOnMap.name
        return place
    }
    mapView.addAnnotations(places)
}

func setRecreationAnnotations() {
    let places = restaurants.map { placeOnMap -> MKPointAnnotation in
        let place = MKPointAnnotation()
        place.coordinate =  CLLocationCoordinate2D(latitude: placeOnMap.latitude, longitude: placeOnMap.longitude)
        place.title = placeOnMap.name
        return place
    }
    mapView.addAnnotations(places)
}

当前,未调用放置相关类别的注释的函数。当点按我的收藏夹视图中的某个项以达到期望的结果时,有没有一种方法可以调用这些方法,还是有一种更好的方法来完成这些操作?

ios swift xcode uicollectionview mapkit
1个回答
0
投票

为了实现您所提供的代码所要求的,有两个重要的缺少步骤:

  1. 当用户点击CollectionView的单元格并通知MapViewController要显示的注释集时会收到通知
  2. 向您的MKMapView提供MKMapViewDelegate

步骤1

为了简洁起见,我假设您的ContentViewController拥有对MapViewController的引用,以便在轻按单元格时可以调用适当的setAnnotations()函数。

class ContentViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
  var mapViewController: MapViewController!
  let imageArray = ...
}

接下来,我们需要在用户点击这些单元格之一时得到通知,为此,我们需要使用UICollectionViewDelegate协议的特定回调:

UICollectionViewDelegate

通过这种方式,当用户选择一个单元格时,MapViewController中的三个setXYZAnnotations函数之一被称为每个

在进入下一步之前,我们有一个小问题需要解决:MKMapView保留添加到其中的所有注释,直到将其删除。这意味着,每次您调用class ContentViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource { ... func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { switch (indexPath.item) { case 0: mapViewController.setPlacesAnnotations() case 1: mapViewController.setBuildingsAnnotations() case 2: mapViewController.setRecreationAnnotations() } } } 函数之一(因此,每次用户单击单元格时),都会在地图上添加一组新的注释。我们有一种简单的方法来丢弃之前插入到地图中的所有注释:

setXYZAnnontation

这样,我们告诉地图视图清除其当前持有的所有注释。确保在之前在每个mapView.removeAnnotations(mapView.annotations) 函数中的每个调用mapView.addAnnotations(_)的右边添加此行。

步骤2

当您在地图上添加注释或叠加层时,需要一种方法告诉您[[how确实要渲染这些元素。这是由setXYZAnnontation完成的,就像MKMapViewDelegate使用MKMapViewDelegate知道要为单元格使用什么UICollectionView一样。

MapViewController是实现MKMapViewDelegate的不错的选择:

UICollectionViewDataSource

现在,您需要在MapViewController中实现的协议方法是UICollectionView,此函数希望您返回一个class MapViewController: UIViewController, MKMapViewDelegate {
  override func viewDidLoad() {
    super.viewDidLoad()

    mapView.delegate = self
    ...
  }
}
与先前插入的指定注释对象关联。

主要可以采用两种方法:

    仅返回mapView(_:viewFor:):裸露的,标准的iOS风格的针脚📍除了颜色,您无法自定义其外观]
  • mapView(_:viewFor:)
      返回您自己的MKAnnotationView或子类,以完全自定义注释的外观。在下面的示例中,我仅使用UIImage。
  • MKPinAnnotationView
    当然,在您的应用中,您希望根据用户选择的特定批注来区分批注视图的外观。

    Note

  • :如果您在地图中插入了大量注释,则这两种方法可能会导致性能问题。在这种情况下,您需要func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { let pinView = MKPinAnnotationView() pinView.pinTintColor = .green return pinView } MKAnnotaionView可重用的批注视图,以便地图可以回收它们。我建议您看一下func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { let iconView = MKAnnotationView() iconView.image = UIImage(named: "pin_icon") return iconView } 并查阅register文档以加深主题。
    © www.soinside.com 2019 - 2024. All rights reserved.