Tracking mode with MapKit - ios

I have a question about UserLocation e MapKit.
I would to follow the user location on the map (automatically moves the map if user location changes) If the user tap (or pan or pinch) the map I would to disable the 'follow mode' (like Apple map app)..
I tried this method:
[_mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:YES];
This work well but I have some questions about it:
Is possible to set a particular zoom level during the 'follow mode'?
I noticed that if they are in 'follow mode' and I make a pinch the map, the 'follow mode' mode is not interrupted. If I still pinch the map (or pan) 'follow mode' is interrupted. I do not understand when you really stop this mode..

I think i know your means, you can try it, in MKMapViewDelegate:
func mapView(_mapView:MKMapView,didChangemode:MKUserTrackingMode,animated: Bool) {
mapView.setUserTrackingMode(.followWithHeading, animated: true)
}
When you scroll or zoom a mapView the MKUserTrackingMode will change,
so you can reset it.

You can set the region or the center of the map to the user location in its delegate methods:
Region:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 200.0f, 200.0f);
[self.mapView setRegion:region animated:YES];
}
Center:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
[self.mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
}
Source: https://stackoverflow.com/a/19518422/3601482

I guess you want to reset the tracking mode back to auto follow:
[_mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:YES];
The question is when to reset. I would suggest
adding a button (like the navigation arrow button from Apple Maps), so the user can decide when to go back to auto tracking
or make a timer which resets on inactivity

Related

How do I specify the zoom level when using an MKUserTrackingBarButtonItem?

I am using a MKUserTrackingBarButtonItem button to allow the user to automatically track their location on a map. The problem is that when they tap this button, it is zoomed too far out. I want it to start at a specified zoom level (i.e. span). How can I achieve this?
When the user taps the button to change to MKUserTrackingModeFollow, it seems to use the same zoom level that the user last manually changed to (i.e. using gestures on the map). Attempting to specify a different zoom level via setRegion or setVisibleMapRect does not affect what zoom level will be used when the mode is changed to MKUserTrackingModeFollow.
Attempting to override mapView:didChangeUserTrackingMode: to set the region causes the mode to be changed back to MKUserTrackingModeNone. Example:
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
if (mode == MKUserTrackingModeFollow) {
CLLocationCoordinate2D center = mapView.userLocation.location.coordinate;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002306, 0.001717);
[mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];
// [mapView setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
}
}
If I attempt to reset the mode immediately after setting the region, it works fine if the user is stationary, but zooms back out if the user is moving.
The simplest solution would be if there was a way to simply specify something like a zoom level for MKUserTraking by sending it my span value. However, since that doesn't seem to exist, what else can I do?
I had the same issue and used a different approach to fix it. You can use the MapCamera function for this instead of that button.
On each new location do this:
MKMapCamera *newCamera = [MKMapCamera cameraLookingAtCenterCoordinate:[newLocation coordinate]
fromEyeCoordinate:[oldLocation coordinate]
eyeAltitude:2000];
[mapView setCamera:newCamera animated:TRUE];
And play with the eyeAltitude.
If the user manually zooms in or out you can read the altitude value from mapview.camera.altitude also don't update the camera when the user is manually using the map.
According to apple documentation used here
https://developer.apple.com/reference/mapkit/mkmapview/1616208-usertrackingmode
Setting the tracking mode to follow or follow​With​Heading causes the map view to center the map on that location and begin tracking the user’s location. If the map is zoomed out, the map view automatically zooms in on the user’s location, effectively changing the current visible region.
Here changing the region does not effect your visible region due to that reason.
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
if (mode == MKUserTrackingModeFollow) {
CLLocationCoordinate2D center = mapView.userLocation.location.coordinate;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002306, 0.001717);
[mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];
// [mapView setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
}
}
So you just need to change center coordinate on didChangeUserTrackingMode instead of changing the whole region
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
if (mode == MKUserTrackingModeFollow) {
[self.mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
}
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
[self.mapView setCenterCoordinate:mapViewuserLocation.location.coordinate animated:YES];
}
on click of MKUserTrackingBarButtonItem change the zoom level
CLLocationCoordinate2D center = mapView.userLocation.location.coordinate;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002306, 0.001717);
[mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];

MKMapView doesn't zoom correctly while user tracking mode is MKUserTrackingModeFollowWithHeading

I created a test project with few lines of code and with two components: MKMapView and UIButton. I ticked mapView option - Shows user location. Also I defined an action for the button, it zooms the map to user location.
Here is code from controller:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
self.mapView.delegate = self;
}
- (IBAction)changeRegion:(id)sender {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.mapView.userLocation.coordinate, 200.0f, 200.0f);
[self.mapView setRegion:region animated:YES];
}
Pretty simple and straightforward, isn't it? But when I tap the button I see weird behaviour: map view zooms to specified region then returns back to original zoom. What's the problem? How can I keep zooming and track user location at the same time?
I notice similar behaviour with MKUserTrackingModeFollow tracking mode.
P.S. I forgot to mention that it's a problem mostly for iOS7
From apple documentation:
Setting the tracking mode to MKUserTrackingModeFollow or
MKUserTrackingModeFollowWithHeading causes the map view to center the
map on that location and begin tracking the user’s location. If the
map is zoomed out, the map view automatically zooms in on the user’s
location, effectively changing the current visible region.
If you want both to adjust the region and to track the user, I suggest you check for location updates and adjust zoom accordingly.
For example:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 200.0f, 200.0f);
[self.mapView setRegion:region animated:YES];
}
EDIT
Instead of setting the region, try just setting the center,
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
[self.mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
}
and let your button action set the zoom, keeping the same center:
- (IBAction)changeRegion:(id)sender {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.mapView.centerCoordinate, 200.0f, 200.0f);
[self.mapView setRegion:region animated:YES];
}
And very important: do not set your mapView to track user. Disable tracking user because now you are tracking it yourself. I think the default is MKUserTrackingModeNone .

Stop MKMapView from moving to user's current location when user moves the map

I am making an app to show some places near the user's current location. When the user moves the map, the map moves the user to his current location, over and over again. So, the user can't see the annotations on the map, because if he moves the map, the map goes back to his current location.
This is what I am doing right now:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if (userLocation)
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 1000, 1000);
MKCoordinateRegion regionDelMapa = [self.mapa regionThatFits:region];
if(isnan(regionDelMapa.center.latitude))
{
NSLog(#"Bad region...");
}else
{
[self.mapa setRegion:regionDelMapa animated:YES];
}
}
}
I have tried some other answers here, but nothing happens. This is not the desired behavior, so how can I stop updating the user's current location?
[self.mapa setRegion:regionDelMapa animated:YES];
That line sets the map region. You're executing that code every time you get an update, thus reseting the area that the map covers. If you don't want the map to re-center itself on the user's location at each update, remove that code from the -mapView:didUpdateUserLocation: method.
If you want to center the map on the user once and then allow the user to scroll away from that location, use Core Location to get the user's location.
Please use this API : [locationManager stopUpdatingLocation];
Add this in your function didUpdateUserLocation .

How do you set initial size in iOS UIMapkit

I want my mapView to display at the initial size (zoom level I determine) with phone location being centred in the map. Once this is done I want the user to be able to change zoom levels and pan to their hearts content. Next time they come into the app I want to reinitialise the map the same as the previous time.
Problem is when I come in it seems to set the map size before it has got a valid location fix.
Can anyone point me at an example that does best practice initialisation?
I solve this problem in next way. I think code is self-explained
- (void)mapView:(MKMapView *)mapView
didUpdateUserLocation:(MKUserLocation *)userLocation
{
if (!_userLocated &&
userLocation.coordinate.latitude != 0.0 &&
userLocation.coordinate.longitude != 0.0)
{
MKCoordinateRegion mapRegion;
mapRegion.center = mapView.userLocation.coordinate;
mapRegion.span = MKCoordinateSpanMake(0.04, 0.04);
[mapView setRegion:mapRegion animated: YES];
_userLocated = YES;
}
}
And dont forget to set UIMapView delegate and Shows user location.

Map View always center map on my location

I use the following code to get my location when a user presses a button
[mapview setShowsUserLocation:YES];
and then the follwoing to center the map to te user's location
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
[mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
}
My question is how to prevent the map from always centering on my location? I want to allow the user to pan the map.
Center on the location only the first time you show the map. Here is some pseudo code...
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if(shouldCenterLocation){
[mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
shouldCenterLocation = FALSE;
}
//do all your other stuff here
}
shouldCenterLocation is a boolean flag that you can set to TRUE the first time the map is shown, then set it to FALSE until you exit the view (or any other condition you have for showing the center location).
edit: you can toggle the state of shouldCenterLocation in the same method that you handle the button press.
I think it came in with iOS5, you can now drop the delegate stuff and just set the userTrackingMode of the MKMapView. Set it to MKUserTrackingModeFollow to make the make move along with the user and then when they start panning the map around it'll turn off the tracking mode automatically, you then just need to provide a button to turn it back on.
On swift 3 I prefer use animated method:
mapView.setUserTrackingMode(.follow, animated: true)
but set property good worked:
mapView.userTrackingMode = .follow

Resources