While trying to provide information about a map location via colored text in the Seattle Trails app I'm working on, I came to the realization that I would need to use a custom annotation callout view to meet my needs. Default callout views use a String value for their subtitle property, which does not allow color. NSAttributedStrings allow color and UILabels have an attributed text property available. The following is a tutorial of the mini-project I used to figure out how to achieve this.
First, set up a project with a map view and connect it to the default view controller via an IBOutlet:
Next, we want to set up a custom pin and view. Create a xib for the view, custom view class and map annotation class. When creating the xib, the size can be adjusted by dragging after setting it to freeform in the attributes inspector. Connect the xib to the view with IBOutlets:
Now the custom pin needs to be added to the map, which requires the view controller to implement MKMapViewDelegate and CLLocationManagerDelegate. The user's current location is obtained from CLLocationManager to drop the annotation pin on it. When getting the user's location, it is important to add NSLocationWhenInUseUsageDescription as a key to the info.plist and request authorization to access location data.
This is an oversimplified way to set up a pin, and it will be used differently in Seattle Trails; however, here the multi colored subtitle is set up with fixed ranges for the colors and then used to initialize a pin. The user location is set as the annotation pin's coordinates, which is then added to the map view.
When the annotation is selected, in didSelectAnnotationView, the custom annotation view is loaded from the xib file. The next part moves the view to be centered over the annotation pin. Since the touched map annotation type is known to be the custom annotation that was added to the map in viewDidLoad, it is casted to that type and stored in customAnnotation. That is used to set the custom view's title and subtitle before adding it as the annotation view to be displayed.
Last, the map region is set to move the map view to the annotation pin. Span x and y determine how far the map zooms in. Because a value of 1.0 is always equal to 69 miles, setting the value to 0.01 narrows down the view to slightly more than half a mile.
I hope this walkthrough ends up being helpful to someone, and I'm eager to receive feedback so that my intention can be better met through iteration. Please leave your comments and this code is available here: GitHub.