MapKit Annotations - show detail when tapping on a plot

I’ve been trying to figure out how to get the detail behind the plots that I have on my map and pop them up for the user to view. Can someone give me a direction I should look for this? I know the detail is getting read into memory, but I’m trying to figure out how to capitalize on that data and show it in another screen when a given pin is tapped.

Much appreciated,

Mike

Hi Mike,

Lookup MKAnnotationView and the mapView function:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
}

This uses the annotation that was added to the mapView and enables you to create an annotationView and use the Callout option to display the annotation which can have a title and a subtitle.

Hey Chris

I already have that, but what I need is when I tap on an annotation I want to bring up another view that has the detail and a photo ( 6 or so fields) of what was at those coordinates. For the life of me I can’t figure out how to use the fields from my array, other than for title and subtitle, but that isn’t what I want to do. Does that make sense?

Thanks - Mike

Hi Mike,

Yes I understand what you are trying to do. During the 100 Days of Swift course I did (one of Paul Hudsons free courses) there was a project named Capital Cities where the MapView had a bunch of pins on it that were manually created. The annotations are configured to be MKPinAnnotationView which have a button attached which is of the type .detailDisclosure. Tapping on that button instantiates a DetailViewController which displays the Wikipedia entry for the Capital City.

Essentially I suppose you could modify that code to do what you wanted to do either by presenting another View Controller or presenting a popover View of some kind with the image and the details you wanted to show.

Hey Chris, thanks for getting back to me. Can you share that project with me?

regards, Mike

No problem Mike.

I’ll upload it to a DropBox link when I get back home.

Chris, thanks for uploading you project. This thing is kicking my butt! I’ve tried a bunch of different things, but nothing seems to work. Even though I see the information in the pin when clicking on it, when I click on the info button, everything is nil. I know it’s a big ask, but could you look at the code below and hopefully something stands out?

//
// MapViewController.swift
// TournamentFishing
//
// Created by Mike Nelson on 2/18/20.
// Copyright © 2020 CIC Solutions. All rights reserved.
//

import UIKit
import MapKit
import CoreLocation
import RealmSwift

class MapViewController: UIViewController {

@IBOutlet weak var mapView: MKMapView!

//var mapView: MKMapView!

var locationManager:CLLocationManager?
var lastKnownLocation:CLLocation?

override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent }

var annotationLocations:Results<MyFish>!


override func viewDidLoad() {
    super.viewDidLoad()
    
    // Create new CLLocation manager
    locationManager = CLLocationManager()
    locationManager?.delegate = self
    
    checkLocationServices()
    
    let realm = RealmService.shared.realm
    let annotationLocations = realm.objects(MyFish.self)
    
    mapView.delegate = self
    createAnnotations(locations: annotationLocations)

}

func createAnnotations(locations: Results<MyFish>) {
    
    for location in locations {
        if location.lat != 0 && location.lon != 0 {
            let annotations = MKPointAnnotation()
            annotations.title = location.species
            annotations.subtitle = location.myFishId

// let lure = location.lure

            annotations.coordinate = CLLocationCoordinate2D(latitude: location["lat"] as! CLLocationDegrees , longitude: location["lon"] as! CLLocationDegrees )

            mapView.addAnnotation(annotations)
            
        }
    }
}

extension MapViewController: MKMapViewDelegate {

func mapView(_ mapView: MKMapView, viewFor annotations: MKAnnotation) -> MKAnnotationView? {

// guard annotations is MyFish else { return nil }
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: “MyFish”) as? MKPinAnnotationView

    if annotationView == nil {
        annotationView = MKPinAnnotationView(annotation: annotations, reuseIdentifier: "MyFish")
        
        annotationView?.canShowCallout = true

        let btn = UIButton(type: .detailDisclosure)
        annotationView?.rightCalloutAccessoryView = btn
    } else {
        annotationView?.annotation = annotations
    }
    
    if annotations is MKUserLocation {
        return nil
    }
    if  let title = annotations.title, title == "Walleye" {
        annotationView?.image = UIImage(named: "redPin")
    } else if let title = annotations.title, (title?.contains("Bass"))!  {
        annotationView?.image = UIImage(named: "greenPin")
    } else if let title = annotations.title, title == "Muskellunge"  {
        annotationView?.image = UIImage(named: "purplePin")
    } else if let title = annotations.title, title == "Northern Pike"  {
        annotationView?.image = UIImage(named: "purplePin")
    } else if annotations === mapView.userLocation {
        annotationView?.image = UIImage(named: "myLoc")

    }
    else {
        annotationView?.image = UIImage(named: "yellowPin")
    }
    
    annotationView?.canShowCallout = true

    return annotationView
}

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
    let selectedAnnotation = view.annotation as? MyFish

AT THIS POINT EVERYTHING IS nil

    let length = selectedAnnotation?.length?.description
    print("\(length)")
    
    let views = Bundle.main.loadNibNamed("CustomCalloutView", owner: nil, options: nil)
    let calloutView = views?[0] as! CustomCalloutView?
    
    calloutView?.dateLabel.text = selectedAnnotation?.dateCreated
    calloutView?.speciesLabel.text = "\(String(describing: selectedAnnotation?.length))\"  \(String(describing: selectedAnnotation?.species))"
    
    calloutView?.center = CGPoint(x: view.bounds.size.width / 2, y: -((calloutView?.bounds.size.height)!)*0.52)
    view.addSubview(calloutView!)
    mapView.setCenter((view.annotation?.coordinate)!, animated: true)
}


func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {

// if view.isKind(of: AnnotationsView.self)
// {
for subview in view.subviews
{
subview.removeFromSuperview()
}
// }
}