Here is my updated code that matches my storyboard. There are two different child view controllers, the map view and the collection view. The ContentViewController also has an animation when the user clicks the button that allows for the card to collapse and expand. The mapView is a separate view. The problem is that when I run this, a new view controller is displayed when showing an animation instead of having just the MapViewController be replaced. Ideally when running this, a user would expand the card view, then click on a collection view cell and then new annotations would populate the top of the screen (because that is where the map view is). With my current code the annotations are not being displayed on screen. How would I fix this so that I can see the respected annotations when clicking on the cell?
Here is the code.
import UIKit
import MapKit
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, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
var placesVal = [PlacesOnMap(name: "place 1", latitude: 12.9716, longitude: 77.5946),
PlacesOnMap(name: "place 2", latitude: 12.2958, longitude: 76.6394),
PlacesOnMap(name: "place 3", latitude: 11.4102, longitude: 76.6950)
]
var buildings = [PlacesOnMap(name: "buildings 1", latitude: 12.9716, longitude: 77.5946),
PlacesOnMap(name: "buildings 2", latitude: 12.2958, longitude: 76.6394)
]
var recreation = [PlacesOnMap(name: "recreation 1", latitude: 28.54693, longitude: -81.393071),
PlacesOnMap(name: "recreation 2", latitude: 28.538523, longitude: -81.385399),
PlacesOnMap(name: "recreation 3", latitude: 28.542817, longitude: -81.378117),
PlacesOnMap(name: "recreation 4", latitude: 28.538985, longitude: -81.404694)
]
//helps create an intial view for the mapView; zooms in on Orlando
let startingLocation = CLLocation(latitude: 28.5383, longitude: -81.3792)
let distanceSpan: CLLocationDistance = 4000
let reuseIdentifier = "cell" // also enter this string as the cell identifier in the storyboard
var items = ["Places", "Buildings", "Recreations"]
override func viewDidLoad() {
super.viewDidLoad()
zoomLevel(location: startingLocation)
}
//controls how much the map is zoomed in based off of intial inputs from the startingLocation variable
func zoomLevel(location: CLLocation) {
let mapCoordinate = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: distanceSpan, longitudinalMeters: distanceSpan)
mapView?.setRegion(mapCoordinate, animated: true)
}
// tell the collection view how many cells to make
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}
// make a cell for each cell index path
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! Cell
// Use the outlet in our custom class to get a reference to the UILabel in the cell
cell.textLabel.text = self.items[indexPath.item]
cell.backgroundColor = UIColor.cyan
return cell
}
// MARK: - UICollectionViewDelegate protocol
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
if(indexPath.item == 0){
setPlacesAnnotations()
}else if(indexPath.item == 1){
setBuildingsAnnotations()
}else if(indexPath.item == 2){
setRecreationAnnotations()
}
mapView?.delegate = self
}
func setPlacesAnnotations() {
let places = placesVal.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)
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let annotationTitle = view.annotation?.title else
{
print("Unable to retrieve details")
return
}
print("User tapped on annotation with title: \(annotationTitle!)")
}
}
class Cell: UICollectionViewCell {
@IBOutlet weak var textLabel: UILabel!
}
Storyboard.
You need to create a UICollectionView
in one ViewController
and then pass the index value to the other ViewController
to display it on MKMapView
.
Created a sample project here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With