簡體   English   中英

點擊集合視圖單元格以向 map 添加注釋

[英]Tapping a collection view cell to add annotations to a map

現在我有一個 map 和一個顯示 map 圖標的集合視圖。 I want to make it so that when one of the icons is selected it displays those different locations within that specific category on the map; 類似於蘋果地圖。

 import UIKit
 import MapKit

 //Creating an outline for the different locations of places on the map
 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 ContentViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

 //Properties of collectionView, that determine number of items in the section and allows a single cell to be reused over and over again
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]
return cell
}

 //creating a constant for variables within the collection view such as the image and the title of the image
  let imageArray = [UIImage(named: "1"), UIImage(named: "2"), UIImage(named: "3")]
 let imageNameArray = ["image 1", "image 2", "image 3"]

 @IBOutlet var mapView: MKMapView!

 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()

mapView?.delegate = self
}

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

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

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

 //calls the functions up above when a cell from the collection view is selected
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch (indexPath.item) {
case 0: setBuildingsAnnotations()
case 1: setPlacesAnnotations()
case 2: setRecreationAnnotations()
default:
    break
}
}
}

目前,沒有調用放置受尊重類別的注釋的函數。 當點擊我的收藏視圖中的項目以達到預期結果時,有沒有辦法調用這些,或者是否有更好的方法來 go 完成此操作?

在此處輸入圖像描述

為了實現您使用您提供的代碼提出的要求,有 2 個重要的缺失步驟:

  1. 當用戶點擊 CollectionView 的單元格時收到通知,並通知 MapViewController 要顯示的注釋集
  2. 為您的 MKMapView 提供 MKMapViewDelegate

步驟1

為簡潔起見,我將假設您的ContentViewController持有對MapViewController的引用,以便在點擊單元格時調用適當的 setAnnotations() function。

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

接下來,當用戶點擊其中一個單元格時,我們需要得到通知,為此我們需要使用UICollectionViewDelegate協議的特定回調:

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()
    }
  }
}

這樣,每次用戶選擇您的一個單元格時,都會調用 MapViewController 中的三個 setXYZAnnotations function 之一。

在進行下一步之前,我們有一個小問題需要解決:MKMapView 保留添加到其中的所有注釋,直到這些注釋被刪除。 這意味着每次調用setXYZAnnontation function(因此,每次用戶點擊單元格)時,都會將一組新注釋附加到 map。 我們有一個簡單的方法來丟棄之前插入到 map 中的所有注釋:

mapView.removeAnnotations(mapView.annotations)

這樣,我們告訴 map 視圖清除它當前持有的所有注釋。 確保在每個setXYZAnnontation函數中調用mapView.addAnnotations(_)之前添加此行。

第2步

當您在 map 上添加注釋或覆蓋時,需要一種方法來告知您希望這些元素如何呈現。 這是由MKMapViewDelegate完成的,就像UICollectionView使用UICollectionViewDataSource來了解要用於單元格的UICollectionViewCell一樣。

MapViewController 是實現 MKMapViewDelegate 的理想選擇:

class MapViewController: UIViewController, MKMapViewDelegate {
  override func viewDidLoad() {
    super.viewDidLoad()

    mapView.delegate = self
    ...
  }
}

現在,您需要在 MapViewController 中實現的協議方法是mapView(_:viewFor:) ,這個 function 希望您返回一個MKAnnotationView以與您之前插入的指定注釋 object 關聯。

您可以采取的方法主要有兩種:

  • 只需返回一個MKPinAnnotationView :一個裸露的、標准的 iOS 風格的 pin
    除了顏色之外,您無法自定義它的視覺外觀
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
  let pinView = MKPinAnnotationView()
  pinView.pinTintColor = .green
  return pinView
}
  • 返回一個MKAnnotaionView或子類您自己的,以完全自定義注釋的外觀。 在以下示例中,我只是使用 UIImage。
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
  let iconView = MKAnnotationView()
  iconView.image = UIImage(named: "pin_icon")
  return iconView
}

當然,在您的應用程序中,您希望根據用戶選擇的特定注釋集來區分注釋視圖的外觀。

注意:如果您在 map 中插入了大量注釋,這兩種方法可能會導致性能問題。 在這種情況下,您需要注冊和出列可重復使用的注釋視圖,以便map可以回收它們。 我建議您看一些快速教程並查閱MapKit文檔以加深主題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM