Custom Annotation view for userlocation not moving the mapview
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.
MKMapView iOS custom user location Annotation not showing/updating position
Yep all the above code works! Finally got it working. So Steps for custom user loc that also updates with your movements are above.
(MapView) Userlocation image changed help to restore
In your viewFor annotation
function add this row in the beginning:
if annotation is MKUserLocation {
return nil
}
Because you don´t want to do anything if it´s the MKUserLocation
.
didUpdateUserLocation not called when view for userLocation is custom
Instead of relying on the map view's location updates, start a CLLocationManager
, set its delegate
and wait for -locationManager:didUpdateToLocation:fromLocation:
(in iOS 5 and lower) or -locationManager:didUpdateLocations:
(iOS 6). You will get much more reliable and plentiful information than using the map view's delegate methods. You probably know the way to do this, but here it is:
#import
- (void)viewWillAppear:(BOOL)animated
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager startUpdatingLocation];
}
// Deprecated in iOS 6
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// Check the age of the newLocation isn't too long ago using newLocation.timestamp
// Set the map dot using newLocation.coordinate
// Set an MKCircle to represent accuracy using newLocation.horizontalAccuracy
}
I had a look at the delegate calls that come in to the mapView's delegate, and returning anything other than nil
stops calls to -mapView:didUpdateUserLocation:
, like you said. Here are the calls in the order they arrive:
- (void)mapViewWillStartLocatingUser:(MKMapView *)mapView
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id < MKAnnotation >)annotation
- (void)mapViewWillStartLoadingMap:(MKMapView *)mapView
- (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error
Presumably the MKUserLocation
object, not the MKMapView
is the object responsible for calling the delegate with update calls. If you check the status of showsUserLocation
and mapView.userLocation
, they both look fine:
NSLog(@"%d %@", mapView.showsUserLocation, mapView.userLocation);
returns 1
and a non-nil object (1
). Maybe the mapView
queries its userLocation
object to get the current location, then sends it to the delegate. If that object has gone, it won't work.
It's a bit strange, but like I said, you'll get better updates from a CLLocationManager
's updates.
Related Topics
Nscamerausagedescription in iOS 10.0 Runtime Crash
How Can a Web Application Send Push Notifications to iOS Devices
(Swift) How to Print "\" Character in a String
Unique Identification of iOS Device for iOS 7.0 and Above
Disable iOS8 Quicktype Keyboard Programmatically on Uitextview
Expandable Tableview in Iphone
High Quality Scaling of Uiimage
How to Pass Multiple Values with a Notification in Swift
Default Keyword in Swift Parameter
How to Check If Uilabel Is Truncated
How to Load a Xib File in a Uiview
How to Run an Action When a State Changes
Wkwebview Does Load Resources from Local Document Folder
Ios: Keep an App Running Like a Service
Phonegap Cdvviewcontroller.H File Not Found When Archiving for iOS