I have an app that has a map with a lot of markers on it, the app notifies the user whenever he approaches one of the markers. I'm using Google Maps iOS SDK for the map, that's mean I use GMSMapView for the map view (mapView).
I want that when the user opens the app via a notification (tap on a notification) the map's camera will automatically be pointing to the notification's marker.
I've tried to do it like this:
AppDelegate.m:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSString *markerIdentifier=[[notification userInfo] objectForKey:#"markerIdentifier"];
GMSMarker *marker=[self markerForIdentifier:markerIdentifier];
[self.aroundersVC.mapView setSelectedMarker:storeMarker];
//Important part:
[self.aroundersVC animateMapToMarkerPosition:storeMarker];
}
AroundersViewController:
-(void)animateMapToMarkerPosition:(GMSMarker*)marker
{
GMSCameraPosition *currentLocationCameraPosition=[GMSCameraPosition cameraWithLatitude:marker.position.latitude longitude:marker.position.longitude zoom:16];
[self.mapView animateToCameraPosition:currentLocationCameraPosition];
}
But it's not working for some reason, anyone knows why?
Thanks!
Use GMSMapview delegate
-(void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position
{
// Do your stuff here
}
This should solve your problem.
Related
I have a GMSMapView with a lot of markers, every marker represents one store of my client, every time the user approaches to one of the markers (to one of the stores) he gets a notification with the address of the store.
I want that when the user taps on a notification (opens the app via notification) the marker will be presented on the map (already selected).
Note: the marker is a property for every Store object, the UILocalNotification stores the Store object's identifier and that's how I find the correct store.
Note 2: I'm working with Google Maps iOS SDK.
I've tried to do it like this:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSString *storeIdentifier=[[notification userInfo] objectForKey:#"storeIdentifier"];
Store *notificationsStore=[self.monitorLocationVC storeForIdentifier:storeIdentifier];
[self.myVC mapView:self.myVC.mapView didTapMarker:notificationsStore.marker];
}
For some reason, the marker isn't being selected when the user opens the app.
I've override mapView: didTapMarker: on myVC.m like that:
-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker
{
return NO;
}
didTapMarker is on GMSMapViewDelegate, it's called by the map to notify your code that the marker has been tapped. It doesn't tap the marker.
You can however set selectedMarker on the map view, to cause that marker to be selected, and to show its info window (if it has one). For example:
self.myVC.mapView.selectedMarker = notificationsStore.marker;
See here for more examples: How to show a Info window in iOS Google maps without tapping on Marker?
-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker
{
viewIwant.hidden=NO;
//or any nib you want
return YES;
}
We are developing IOS app. Where user can drop pin (Car, Bus etc) on map and define direction (angle) as well. I know how to drop pin but What I need to do for direction angle?
Here are details of my problem. As you can see a pin dropped at may. User can set direction to any angle with his fingers. Like user rotate photo. I need to show pin to other user app users to with exact direction angle. What I need to persist for that at central database or web API end that can be used to place that pin on other user's app.
CLLocationManagerDelegate protocol has a method called - (void)locationManager:didUpdateHeading: in which you can get a hold on users heading aka direction.
Sample:
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
CLLocationDirection direction = newHeading.magneticHeading;
}
NOTE: for this method to be called, you have to call CLLocationManager's instance method - (void)startUpdatingHeading. Like this:
[self.locationManager startUpdatingHeading];
Then if you have a custom view for MKUserLocation annotation you can rotate it based on previously received direction in above method.
Sample:
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
// rotated custom view code
}
}
I have a question about MapKit. I set the userTrackingMode property to move the map according to the user position update.
[_mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:YES];
Is there a way to be alerted when you exit from this mode?
From the Apple Docs on MKMapViewDelegate Protocol:
mapView:didChangeUserTrackingMode:animated:
Tells the delegate that the user tracking mode changed.
(void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated
I am using am mapview and sometimes my map will zoom onto my users location when I open it but sometimes it will zoom to the middle of an ocean. I don't know what is causing this, this is the code I am using for zooming. I don't want the map to track the user but just zoom to their location once they open the map
-(void) viewDidAppear:(BOOL)animated{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.mapView.userLocation.coordinate, 600.0f, 600.0f);
[self.mapView setRegion:region animated:YES];
}
-(void) viewDidLoad{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
}
I encountered this issue before. It seems that mapView is slow to load and detect user location sometimes, resulting in your code in viewDidAppear being executed before the map view can check user's location. Thus, the spot in the ocean.
It will be better to use mapView's delegate to display user location when it's ready:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if(isShowUserLocation)
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 600.0, 600.0);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
isShowUserLocation = NO;
}
}
Set isShowUserLocation = YES in viewDidLoad. This ensures the user location is shown once on entry and also selectively when you need it.
Edit 1:
#implementation MapViewController
{
BOOL isShowUserLocation;
}
-(void) viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
isShowUserLocation = YES;
}
Edit 2:
Alternatively, use CLLocationManager - see this post. It allows you stop the updating. Do include CoreLocation.framework. You may need to handle some nitty-gritty issues when interacting CLLocationManager with MapView though.
When you pass 0's for lat and long, you will git a spot in the middle of the ocean south of Ghana in Africa.
i am loading a mapviewcontroller when the view map button is pressed from my mainviewcontroller:
- (IBAction)mapButton:(id)sender {
MapKitDisplayViewController *mapKitDisplayView = [[MapKitDisplayViewController alloc] init];
[self presentModalViewController:mapKitDisplayView animated:YES];
[mapKitDisplayView release]; mapKitDisplayView = nil;
}
On startup of this map view this method is called, which correctly zooms to the users location:
- (void)mapView:(MKMapView *)myMapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
myMapView.showsUserLocation = YES;
NSLog(#"didUpdateUserLocation = '%#'", userLocation);
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([userLocation coordinate], 20000, 20000);
[myMapView setRegion:region animated:YES];
}
I have a done button on this screen that dismisses this view:
- (IBAction)mapDoneButton:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
At this stage the user is taken back to the main view controller, however when i press the view map button again, the didUpdateUserLocation method is never called! Hence, the map view is zoomed out to the default one and wont zoom in as before.
How can i get it to be called again?
thanks
MKMapView object doesn't trigger an update on user location on its own. You need to activate the search by setting showsUserLocation = YES. This will then fetch the user's location and then the delegate method mapView:didUpdateUserLocation: is called. So set this value to YES on viewWillAppear: and once you've the user location you can set it to NO to stop tracking the user. If you don't do that, it periodically updates the user location and calls the delegate method. Without doing this, user location should be unreliable.
What i do is next:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
[[NSNotificationCenter defaultCenter] postNotificationName:#"gotUserLocation" object:self];}
then in viewDidLoad check of user location is available. if it is not register view controller as reciever for that notification:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(zoomToLocation) name:#"gotUserLocation" object:nil];
if user location is available just call zoomToLocation method