How to change MKMapView's user-location blue dot to an image of choice?

Solution 1:

In the viewForAnnotation: method of MKMapViewDelegate probably you would be having the code like this.

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {

    if (annotation == mapView.userLocation) return nil;
    ...

We return nil if the annotation is userLocation to let the mapView display the blue dot & circle animation. In order to show our custom annotation for userLocation just remove the line return nil; and do your customization there.

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {

    static NSString* AnnotationIdentifier = @"Annotation";
    MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];

    if (!pinView) {

        MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];   
        if (annotation == mapView.userLocation){
           customPinView.image = [UIImage imageNamed:@"myCarImage.png"];
        }
        else{
            customPinView.image = [UIImage imageNamed:@"mySomeOtherImage.png"];
        }
        customPinView.animatesDrop = NO;
        customPinView.canShowCallout = YES;
        return customPinView;

    } else {

        pinView.annotation = annotation;
    }

    return pinView;
}

Solution 2:

Here is Swift 2.0 version in which you might have multiple pins.

In this code CustomAnnotation is just an MKAnnotation subclass. Basically if the annotation is not the kind of one of your custom classes, then its the user location pin.

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{
    // This is false if its a user pin
    if(annotation.isKindOfClass(CustomAnnotation) == false)
    {
        let userPin = "userLocation"
        if let dequeuedView = _view.mapView().dequeueReusableAnnotationViewWithIdentifier(userPin)
        {
            return dequeuedView
        } else
        {
            let mkAnnotationView:MKAnnotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: userPin)
            mkAnnotationView.image = UIImage(named: C_GPS.ROUTE_WALK_ICON_NAME)
            let offset:CGPoint = CGPoint(x: 0, y: -mkAnnotationView.image!.size.height / 2)
            mkAnnotationView.centerOffset = offset

            return mkAnnotationView
        }

    }

    let annotation = annotation as? CustomAnnotation
    if(annotation == nil)
    {
        return nil
    }

    let endPointsIdentifier = "endPoint"
    if let dequeuedView = _view.mapView().dequeueReusableAnnotationViewWithIdentifier(endPointsIdentifier)
    {
        dequeuedView.image = annotation!.uiimage
        return dequeuedView
    } else
    {
        let mkAnnotationView:MKAnnotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: endPointsIdentifier)
        mkAnnotationView.image = annotation!.uiimage
        let offset:CGPoint = CGPoint(x: 0, y: -mkAnnotationView.image!.size.height / 2)
        mkAnnotationView.centerOffset = offset

        let gesture = UITapGestureRecognizer(target: self, action: "routeTouched:")
        mkAnnotationView.addGestureRecognizer(gesture)

        return mkAnnotationView
    }
}

Solution 3:

Ok, here is the Swift version:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {

    let identifier = "User"

        var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)

        if annotationView == nil{
            annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            annotationView.canShowCallout = true

        } else {
            annotationView.annotation = annotation
        }

    annotationView.image = UIImage(named: "image")

    return annotationView

}