9

I tried to set the user tracking mode in the viewDidLoad method (and in viewWillAppear). If I set it to MKUserTrackingModeFollowWithHeading (value of 2), it does not take effect. Actually, right after setting its value to 2, if I print it value, it is 1, why? I have never seen such a thing in any programming experience!

Here is how I set it:

[self.mapView setUserTrackingMode: MKUserTrackingModeFollowWithHeading 
                         animated: YES];

If I do the same in the viewWillAppear method, the effect is the same. However, the second time this view is displayed, the setting will take effect. (I have a tab viewcontroller, I switch the view to another and then switch back).

The way I see it does not take effect is two measures: (1) print its value right after setting it (2) in the map view, the heading is not displayed.

What the is going on?

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
user1020156
  • 101
  • 1
  • 3

5 Answers5

15

I know this is a really old post, but just in case it helps others out there looking for a solution, the reason is because you need to set the userTrackingMode after the map has loaded. So set your class as the delegate, then add this delegate method:

- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {
    mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
}
Daniel
  • 1,151
  • 1
  • 9
  • 15
3

I also have the same issue. Cannot find any information in the map header about it not working, or working for that matter.

The solution I've implemented is to use a custom CLLocationManager to retrieve the heading, and then rotate the map appropriately. See this answer for some help using this method: Rotate MapView using Compass orientation

Also note that the iOS simulator doesn't currently allow for heading simulation.

Community
  • 1
  • 1
mm282
  • 453
  • 3
  • 7
  • 1
    Interestingly, the mapView:didUpdateUserLocation: method in the MKMapView delegate class is never called a single time although I do see the current location (the blue dot) when the map is loaded. I made sure that the "showsUserLocation" property is set to YES. – user1020156 Nov 28 '11 at 03:23
  • After setting the mapview's delegate (as self), the mapView:didUpdateUserLocation is now called. But when I touch or zoom the screen, the location heading disappears and the map rotates back to a regular state. – user1020156 Nov 29 '11 at 01:39
  • @user1020156 I believe this is normal behaviour to have the map rotate back to normal when you pan across the map (though zoom doesn't cause the map to rotate back to normal for me). This is the behaviour the default "Maps" application exhibits on iOS. Also you can find out whenever the tracking mode has been changed through mapView:didChangeUserTrackingMode:animated on the mapView delegate http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapViewDelegate_Protocol/MKMapViewDelegate/MKMapViewDelegate.html – Bryce Thomas Mar 17 '12 at 09:41
0

Could it be that it is being called too early? try putting the setUserTrackingMode call in the viewDidAppear method, and make sure you haven't set a different value in Interface Builder (the gui part of Xcode)

Craig
  • 8,093
  • 8
  • 42
  • 74
0

I was having this problem as well. Even though I had already set showsUserLocation to YES and userTrackingMode to MKUserTrackingModeFollowWithHeading in -viewDidLoad, the heading still was only being displayed every once in a while. After checking 'Shows User Location' in the nib for good measure, as well as moving the setUserTrackingMode: to -viewDidAppear, it started consistently showing the heading. I would say that -viewDidLoad is called too early for the mapView. Not sure why, though.

Mark Mckelvie
  • 343
  • 4
  • 13
0

So the reason why this error occurs:

UIMapView is not loaded yet in the viewDidLoad.

Putting the code in the methode mapViewDidFinishLoadingMap is also not a good idea because it's not said that method will be called. The method is not called when tiles are cached (for example if you have another mapview in you app on a different place zoomed to the same tiles).

So it's not a good idea to put it in the mapViewDidFinishLoadingMap either.

Final solution:

Create a private boolean and set it to false in the viewDidLoad

BOOL _didFollowUserAlready;

Set the mapview delegate to self and add this method:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    if(!_didFollowUserAlready)
    {
        _didFollowUserAlready = TRUE;
        [mapView setUserTrackingMode:MKUserTrackingModeFollow animated:TRUE];
    }
}
Sjoerd Perfors
  • 2,317
  • 22
  • 37