现在,我有一个地图和一个显示该地图图标的集合视图。我要这样做,以便在选择其中一个图标时在地图上该特定类别内显示那些不同的位置;类似于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)
}
当前,未调用放置相关类别的注释的函数。当点按我的收藏夹视图中的某个项以达到期望的结果时,有没有一种方法可以调用这些方法,还是有一种更好的方法来完成这些操作?
为了实现您所提供的代码所要求的,有两个重要的缺少步骤:
为了简洁起见,我假设您的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(_)
的右边添加此行。
当您在地图上添加注释或叠加层时,需要一种方法告诉您[[how确实要渲染这些元素。这是由setXYZAnnontation
完成的,就像MKMapViewDelegate
使用MKMapViewDelegate
知道要为单元格使用什么UICollectionView
一样。
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文档以加深主题。