MapKit pin color

How can I add two pins with different colors? One with “Red” and the other one with “Purple” color.

Details?
Is that using our MBS Plugin classes?

Yes. I use example: “MapKit Custom Icons example” from the folder “MacFramework/MapKit”. In this example I can change the pin color only for all visible pins. I need two or more pins with different colors at the same time.

For our plugin the MKPinAnnotationViewMBS class has a pinTintColor field to pick any color you like for the :pushpin:.

You create a new pin annotation class and add it to the viewForAnnotation

Alternatively make it dependent on some other property, so in the map’s ViewForAnnotation instead of

Select Case popIconTypeSelection.Text

do

Select Case annotation.title
  
Case "Start"
  Return GetViewForPin( annotation, "Red Pin", "Red Pin", "red", 1000 )
  
Case "Finish"
  Return GetViewForPin( annotation, "Green Pin", "Green Pin", "green", 1000 )
  
Case "Water"
  Return GetViewForPin( annotation, "Purple Pin", "Purple Pin", "purple", 1000 )

But it would be better to use a custom pin annotation and give it a property that you can use for the selector like I do for the custom annotations Car and Driver (and note that in GetViewForCustomAnnotation you need to cast the annotation).

Note that GetViewForPin and GetViewForCustomAnnotation are just convenience functions to simplify the code.

Screenshot

Hi Markus,
that looks good. Have you an example project for this?

One of the things you have to understand about using MapKit is that you have annotations (very simple “cheap” objects) and views (very expensive memory-hungry objects - that’s why the map reuses views as much as possible with the help of a limited pool of cached views and the reuse identifier).

There might also be a lot of other annotations on your map other than the ones you are now interested in.

The map passes ONLY the annotations currently visible into ViewForAnnotation to get a view. By default that is a red pin.

If you want ANYTHING other than a red pin (eg a green pin), then you need to return a customised view.

If you also want different pin colors (or icons) aka different views then you need to be able to determine which view you need. So you need SOME property that you can select for.

That property could be the Title (like “Start”, “Finish”, “Water”) or SubTitle property, but it is MUCH better to make a new Annotation class and give it a property to select for as Title and SubTitle are usually shown when you click a pin - and that massively restricts what you can put in there.

So add a new class cLocation, set its super to MKPointAnnotationMBS, and give it a property

selector as String

You’ll probably also want to keep track of all your locations so add an array to the window:

Locations() as cLocation

Now you need to define a custom view for your Location annotation objects. In the simplest case you could just create a MKPinAnnotationViewMBS and change its properties, so in ViewForAnnotation you do:

If annotation IsA cLocation Then
    
  dim Location as cLocation = cLocation(annotation)

  select case  Location.selector

  case "purple pin"  

      // create a variable of type AnnotationView and try to assign a view
      //   with the same reuseIdentifier to it from the reuse pool of views
      
      Dim viewForPin As MKPinAnnotationViewMBS = MKPinAnnotationViewMBS(mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier))

      // either a suitable annotation view is returned, or Nil
      // so test for Nil:
      //    if it is Nil then we have a view that we can return
      //    if not we create a new view to customise and return
      
      If view <> Nil Then
        Return view
      Else // create a new one
        view = New MKPinAnnotationViewMBS( annotation, "purple pin" )
      End If 

      // set up display priority
      view.displayPriority = displayPriority

     // set up collision mode 
     view.collisionMode = 1  // circular

     // set up clustering
     view.clusteringIdentifier = "Purple Pin Cluster"

    // set up callout
    view.canShowCallout = True

    view.pinTintColor = MKPinAnnotationViewMBS.PurplePinColor 

    // hook the annotation to the view
    view.annotation = annotation

    Return view

  case "pink pin"
  …

  End Select

But if you want to customise the view even more (eg have an image) then you should not use an MKPinAnnotationViewMBS but an MKAnnotationViewMBS.

Btw if you have xDev I wrote a series about MapKit with 10 articles - I would recommend to read part 6 in xDev 18.5 (Sep/Oct 2020 issue)

1 Like

I would recommend to read part 6 in xDev 18.5 (Sep/Oct 2020 issue) and part 7 in xDev 18.6 (Nov/Dec 2020 issue)

You can download the project from xDev 18.5 here and from xDev 18.6 here

Ooops - that should of course be

      Dim view As MKPinAnnotationViewMBS = MKPinAnnotationViewMBS(mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier))

P.S. Searching for info you’ll probably need to look at Apple’s documentation and Swift code. There is one difference you should be aware of.

Xojo has classes and interfaces (aka method definitions). The important difference is that classes are in a hierarchy (eg superclass and subclass), whereas interfaces cut across hierarchies (any class can implement an interface).

In Swift EVERYTHING is an object (even integers), and an annotation is a protocol, what Xojo calls an interface. But in Swift protocols can have properties too - so a Swift protocol with properties cannot be implemented as an interface in Xojo (as that only allows method definitions - which is a shame). Instead the annotation protocol in Swift’s MapKit is implemented as a class in Xojo which means your annotations must be subclasses of it …

Thank you, now I know what I must do. Also I will take a deeper look into xDev magazine.

This is the result of my first try.

2 Likes