MapKit Tutorial: Getting Started

Hello, Audrey.
i’m deploying my project to iOS 9 and i’m having following error while running your code. Please advise.

"
ERROR /BuildRoot/Library/Caches/com.apple.xbs/Sources/VectorKit_Sim/VectorKit-1230.31.8.23.3/GeoGL/GeoGL/GLCoreContext.cpp 1763: InfoLog SolidRibbonShader:
ERROR /BuildRoot/Library/Caches/com.apple.xbs/Sources/VectorKit_Sim/VectorKit-1230.31.8.23.3/GeoGL/GeoGL/GLCoreContext.cpp 1764: WARNING: Output of vertex shader ‘v_gradient’ not read by fragment shader
?

if you google the warning text of peculiar errors like this, often something shows up:

it’s a bug in the simulator, but works ok on a device; it’s been reported to Apple

Great tutorial! I was able to accomplish without to much trouble.

At this point i would like to know what would be the best approach to change the pin image for a custom one. Is this possible?

Thanks in advance.

MKAnnotationView has an image property: check out the documentation.

This tutorial uses it — scroll down to the Annotations section: https://www.raywenderlich.com/87008/overlay-views-mapkit-swift-tutorial

do you have mapView.delegate = self in viewDidLoad ?

it’s easy to overlook — it’s a 1-line instruction just before you run the single annotation version of the app.

without this, the mapView doesn’t use your viewFor annotation method in the MKMapViewDelegate extension, so it never sees your view.pinTintColor setting

happy coding! :]

set a breakpoint in the viewFor annotation method, to see if it’s being called, then step over to see what’s happening with pinTintColor

Hello! Can you show please example, where image instead pin? I don’t understand how to change pinImage to view.image.

do you need something different from this? I don’t know of any other way:

You wrote “You could replace the pinColor method with a pinImage method in Artwork.swift and set view.image instead of view.pinColor in ViewController.swift.”, can you help please how to make it?

func pinImage() -> UIImage  {
  switch discipline {
  case "Sculpture", "Plaque":
    return UIImage(named: "image1")!
  case "Mural", "Monument":
    return UIImage(named: "image2")!
  default:
    return UIImage(named: "image3")!
  }
}

Also, use MKAnnotationView instead of MKPinAnnotationView:

func mapView(_ mapView: MKMapView,
  viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    if let annotation = annotation as? Artwork {
      let identifier = "artPin"
      var view: MKAnnotationView
      if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) { // 2
          dequeuedView.annotation = annotation
          view = dequeuedView
      } else {
        // 3
        view = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        view.canShowCallout = true
        view.calloutOffset = CGPoint(x: -5, y: 5)
        view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView
      }
      
//        view.pinTintColor = annotation.pinTintColor() 
      view.image = annotation.pinImage()
      return view
    }
    return nil
}

It Works!! Thank you very much!! Respect!!

Hello, Audrey.
Can you help please. How to make big annotation? In my program address does not fit.

In viewFor annotation, after setting rightCalloutAccessoryView, set up detailCalloutAccessoryView:

let detailLabel = UILabel()
detailLabel.numberOfLines = 0
detailLabel.text = annotation.subtitle
view.detailCalloutAccessoryView = detailLabel

This lets the label use as many lines as it needs, for example (I doubled the subtitle, to make it longer):

view = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView
let detailLabel = UILabel()
detailLabel.numberOfLines = 0
detailLabel.text = annotation.subtitle
view.detailCalloutAccessoryView = detailLabel

After that messed subtitles

continue to use MKPinAnnotationView, as shown in the tutorial, not MKAnnotationView

Drago’s image annotation isn’t a pin, so I told him to use MKAnnotationView

Can you please send example in cod?

func mapView(_ mapView: MKMapView,
             viewFor annotation: MKAnnotation) -> MKAnnotationView? {
  if let annotation = annotation as? Artwork {
    let identifier = "artPin"
    var view: MKPinAnnotationView
    if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
      as? MKPinAnnotationView { // 2
      dequeuedView.annotation = annotation
      view = dequeuedView
    } else {
      // 3
      view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
      view.canShowCallout = true
      view.calloutOffset = CGPoint(x: -5, y: 5)
      view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView
      let detailLabel = UILabel()
      detailLabel.numberOfLines = 0
      detailLabel.text = annotation.subtitle
      view.detailCalloutAccessoryView = detailLabel
    }
    view.pinTintColor = annotation.pinTintColor()
    return view
  }
  return nil
}

All annotations messed up after that

  1. download the Swift 3 version: https://koenig-media.raywenderlich.com/uploads/2015/03/HonoluluArt-Swift3.zip
  2. build and run to check that it works; if it doesn’t, restart Xcode, or restart your Mac, or reinstall Xcode until it does
  3. add the 4 lines for the detail callout accessory view in viewFor annotation
  4. build and run; tap the green pin in my screenshot above — the detail label should show the full subtitle in 2 lines
  5. replace Artwork with your data object

Hello! Can you help please? How can I make button, which make route, when tapped? No information button, my button.