Group Group Group Group Group Group Group Group Group

MapKit Tutorial: Getting Started |

Learn to use the powerful MapKit framework to build an interactive map, displaying location details and launching Maps for driving directions.

This is a companion discussion topic for the original entry at

Hey there! thank you for your Tutorial! I’ts awesome and I learned a lot. I now try to figure out, if a user would Press on the ‘‘info’’ Button on the Annotation, instead to bring the user to the Maps App, would id be Possible to show them a Picture in Fullscreen of the Art? I couldn’t find any Tutorials for this on the internet.

Hi There, You could definitely do that yes. You’d need:

  • A full screen image of the artwork
  • A UIViewController that contains a UIImageView

When the info button is tapped, you could create an instance of your view controller, set it’s image view’s image to be your full size one, and then present it modally. There’s some handy documentation about this in Apples view controller programming guide:

Hello, I followed your steps, but just after adding the pictures to the annotations you lose the name of the place under the annotation. ok we get it back in the CalloutAccessoryView but is it possible to keep also the title under the annotation, useful when the map is displayed and to see the name of the different places or place to click on all the annotations before finding the right one. thank you

Hi @fabrice,
The ArtworkView subclasses MKAnnotationView which is a very simple annotation and only has an image property that you can set, as we did in the tutorial. But you can always add a UILabel to the ArtworkView. If you only set the image, the annotation view’s frame will match the size of the image. If you want a label too, there will be some extra work to do setting the right frame for the custom annotation view and laying out the image and label, but it can be done.

That’s why the marker annotation and pin annotation view classes that MapKit provides are so useful. All that work is done for you.

Good Luck!

Hi - thanks for the great tutorial, it’s actually the only method I’ve found that has allowed me to reliably change the colour of map points. I did notice that at the beginning of the tutorial you use dequeueReusableAnnotationView but at the end you don’t use it. Should it be possible to use it and get the same outcome ?
I am building an app that has 1400 points on the map and it is suffering from performance issues with zooming and browsing the map.


Hi @jtapping,
When you make a custom annotation view, and use

mapView.register( ArtworkMarkerView.self, 
  forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier) 

You’re doing the same thing as using the dequeueReusableAnnotationView(withIdentifier:) method, MapKit handles the view reuse automatically for you.

ah ok thanks for explaining

Hi, This is a little off topic but I have followed this tutorial in order to display 1400 points on a map but I have come across memory management issues when I remove the annotations and then add them again. The memory isn’t released so I am assuming this is a memory leak.
Can someone point me in the right direction in regards to releasing memory in relation to this mapkit example please? I have looked into ARC and weak / unowned self etc but I haven’t managed to put it into practice relating to the tutorial. thanks!

Hi @jtapping, are you open to sharing some code? That’d make it easier to see what might be the issue. Other than that have you tried using Xcode instruments? There’s a Leaks one that is just for this purpose.

Hi yeah of course I can share code, although it’s literally the code from the tutorial slighty modified for a bike sharing app. I have debugged in Xcode and this shows that there are strong references to the annotationviews and to a favouriteButton that I added.


import Foundation
import MapKit

class StationMarkerView: MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
willSet {

        guard let station = newValue as? Station else {
        canShowCallout = true
        let mapsButton = FavouriteButton()
        let  bool = station.is_favourite
        let image = bool! ? "star.fill": "star"
        mapsButton.setBackgroundImage(UIImage(systemName: image), for: .normal)
        rightCalloutAccessoryView = mapsButton
        markerTintColor = station.markerTintColor
        glyphImage = station.glyphImage


import UIKit

class FavouriteButton: UIButton {

override init(frame: CGRect) {
    super.init(frame: frame)
required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

func initButton() {
    frame.origin =
    frame.size = CGSize(width: 32, height: 32)
    tintColor =
    adjustsImageWhenHighlighted = false
    addTarget(self, action: #selector(FavouriteButton.activateButton), for: .touchUpInside)

@objc func activateButton(){
    if currentBackgroundImage == UIImage(systemName: "star") {

        setBackgroundImage(UIImage(systemName: "star.fill"), for: .normal)
    } else {
        setBackgroundImage(UIImage(systemName: "star"), for: .normal)


Strong references are not bad by themselves, it’s a retain cycle you watch out for. Where two objects have a strong reference to each other that prevent them from being released. I can’t see anything that would cause a retain cycle in the code above, but MapKit does advise against repeatedly adding and removing annotations for performance reasons.

Also, one issue might be that your favourite button is not being reused, every time an annotation is set to an annotation view, you create a new favourite button. Even if the annotation view already has one. That might be something to investigate.

Sorry I couldn’t find a quick answer, but hope that helps.

ok interesting thanks a lot.