Custom Annotation view for userlocation not moving the mapview
Asked Answered
M

2

13

Can we have custom annotation view for the users current location in iOS?

I need to remove the blue dot (with circles) with my own custom view (say some ping pin). Is it possible to do this?

If we do, does this pin move to new location when there is change in user's location? Or do we need to handle it programmatically?

I observed that if we use default blue dot for user's current location, then its gets updated in the map when there is change in user location.

I just want to know if this can be done with our own custom view.

Musty answered 11/7, 2012 at 12:32 Comment(0)
E
14

Yes, you can have a custom view for the user's location.

Unfortunately, it's harder to implement than it should be because even though the documentation for the viewForAnnotation delegate method claims that you can just supply your own view if the annotation class is MKUserLocation, the custom view does not then continue to move with the user's location. In fact, when a custom view is returned for MKUserLocation, the map view stops updating the user location entirely (the map view's didUpdateUserLocation delegate method no longer fires). I believe this is a bug.

A workaround is to use CLLocationManager and a custom annotation...


Make sure showsUserLocation is NO or unchecked on the map view.

Declare properties for a CLLocationManager and a custom annotation using a custom class that implements the MKAnnotation protocol (or you could just use the generic MKPointAnnotation class).

In viewDidLoad or some other appropriate place, create the CLLocationManager, set its delegate and call startUpdatingLocation.

In the location manager's didUpdateToLocation delegate method (not the map view's didUpdateUserLocation delegate method), create or update your custom annotation:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    if (myUserLocAnnot == nil)
    {
        self.myUserLocAnnot = [[[MyUserLocClass alloc] init] autorelease];
          //remove the autorelease if using ARC
        myUserLocAnnot.title = @"You are here";
        myUserLocAnnot.coordinate = newLocation.coordinate;
        [mapView addAnnotation:myUserLocAnnot];
    }
    else
    {
        myUserLocAnnot.coordinate = newLocation.coordinate;
    }
}

Finally, in the map view's viewForAnnotation delegate method, you would return a custom annotation view if the annotation is your custom user location annotation.

Expressway answered 11/7, 2012 at 15:16 Comment(11)
faced the same issue, maybe we can raise a bug to appleVenice
Thanks Anna, Its working now. Even I suspect there is a bug in mapview which doesn't show up our custom annotation view for userlocation when we set it.Musty
But one more issue I am facing here is, as soon as start location update, I get the call back to locationManager:didUpdateToLocation: fromLocation method where I create the annotation and add it to map, but map is not showing my custom view even though I am returning custom view. If I switch off the location and on the location, it works. Is there any issue here?Musty
I don't see that issue. Are you calling startUpdatingLocation in viewDidLoad? Does viewDidLoad do any other kind of UI-blocking synchronous operation?Expressway
@AnnaKarenina: I am making call to startUpdatingLocation in viewDidLoad. There is no UI blocking code.Musty
@AnnaKarenina: Its working fine. The issue is with device. I guess the device is not returning the location change update. I tested in another device and it worked well. Does this happen with devices?Musty
@AnnaKarenina using your suggestion above would I be right in thinking that my custom annotation location will not initially show until I move around and my location updates?Drawstring
@AlexMcPherson: In the above example, technically yes -- since the annotation is not added until you get a location update. But iOS usually calls didUpdateToLocation soon after you call startUpdatingLocation with the most recent known location even if you don't move (unless location services is turned off, not authorized, or there's an error). But you can always add the annotation before any location update (eg. in viewDidLoad) using some default or previously saved value.Expressway
@AnnaKarenina many thanks for you reply Anna this has been driving me crazy. I posted my code here if you wouldnt mind having a look #16191420Drawstring
@AlexMcPherson: This answer may have been before iOS 6 which uses the new delegate method didUpdateLocations instead or maybe the CLLocationManager's delegate isn't set. I'll look at your question later when I get a chance.Expressway
@AnnaKarenina many thanks I see your the master of iOS maps so I hope you didn't mind the contact...Drawstring
C
0

Here is the answer in 2021.

Swift 5, XCode 12.

if annotation.isKind(of: MKUserLocation.self) {
            let userIdentifier = "user_location"
            
            if let existingView = mapView
              .dequeueReusableAnnotationView(withIdentifier: userIdentifier) {
              return existingView
            } else {
              let view = MKAnnotationView(annotation: annotation, reuseIdentifier: userIdentifier)
              view.image = #imageLiteral(resourceName: "dark_haulerIcon")
              return view
            }
            
        }

And you don't need to write logic for moving the annotation. Come on, It will automatically get done. Just use the above logic.

Cringe answered 31/3, 2021 at 7:54 Comment(1)
The annotation is not moving with the user's location. Am I missing something?Hardshell

© 2022 - 2024 — McMap. All rights reserved.