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.
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
}
}
In my app, if location services is turned off, it prompts the user: Turn On Location Services to Allow "MyAPP" to Determine Your Location.
The two option buttons are Settings and Cancel.
How do I handle when the user presses cancel?
Is there any delgate method to handle the cancel button press ?
Maybe this might work for what you want.
First, conform to the UIAlertViewDelegate protocol in your header file.
Then there's a delegate method you can implement.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// if the alert view that appeared has titled "Location Denied" and user pressed on cancel button (cancel button is button at index 0)
if(alertView.title isEqualToString:#"Location Denied"] && buttonIndex == 0)
{
// do something
}
}
// through Button name in UIAlertview you can access which Button you are pressed*
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"cancel"])
{
}
}
Problem: It seems I can't stop Core Location from sending updates to my app / tracking.
What am I doing: In my viewWillAppear I call self.locationManager and pass it to a method to show user's location on the map (an instance of MKMapView). The getter is overridden to check for availability of the serive, to see whether its authorized. If so, it allocs/inits and startMonitoringSignificantLocationChanges and returns.
In viewDidDisappear, I call [self.locationManager stopUpdatingLocation]. But still I can see the location icon in the status bar. Even when I terminate the app by double tapping the home button and closing it, the icon is still there... even after extended amount of time (10+ minutes). When I go to the Settings App, it tells me that my app is still using location services (purple icon).
Question: What am I missing here? Why location update doesn't stop?
Thanks in advance.
The opposite of startMonitoringSignificantLocationChanges is not stopUpdatingLocation, it is stopMonitoringSignificantLocationChanges.
You probably want to replace startMonitoringSignificantLocationChanges with startUpdatingLocation for the sake of more regular updates, unless you have a specific reason for monitoring only for significant location changes.
Check out the CLLocation documentation for further detail.
I too just experienced the same problem as Canopus. It appears that even if stopUpdatingLocation is called the navigation pointer still resides on the status bar if I have showUserLocation enabled. Perhaps this is a bug? It may be as I am running and testing with iOS 4.2.1 and this issue may have been fixed in a later SDK.
I would think that if stopUserLocation is called it would also stop showing the user location since the view I am using it in has already disappeared and is subsequently deallocated.
It appears that you must set showUserLocation to NO before stopping user location updates.
Anyway, in my viewDidLoad method I have the following code:
self.mapView.showsUserLocation = YES;
More code...
- (void)viewWillDisappear:(BOOL)animated
{
if (locationManager)
{
mapView.showsUserLocation = NO;
[locationManager stopUpdatingLocation];
}
[super viewWillDisappear:animated];
}
- (void)dealloc
{
if (locationManager)
{
[locationManager release];
locationManager = nil;
}
(other code)
}
Swift:
Your map AND location manager both need to be stopped:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
locationManager.stopMonitoringSignificantLocationChanges()
locationManager.stopUpdatingLocation()
mapView.showsUserLocation = false
}
You can debug/check location services usage right there in Xcode, in the debug navigator under Energy Impact.
I solved this setting nil to locationManager property after delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// Your code getting coordinates
//Here set nil
locationManager = nil;
}
My app requests "always" auth. Only a certain feature within the app requires that. If the user turns that feature off then on app close we can stop location updates (with the goal of saving battery and removing the location icon from the status bar). I too thought stopping was not working because after app close the location icon in the status bar was still there even though my app was the only app running on my phone with location access and "on app close" I just told it to stop updating locations.
For me the solution was to be a bit more patient and then I realized that it takes iOS about 10-15 seconds to turn off location hardware and update the status bar. I didn't have to nil out my location manager or anything special, just stopped updates on app close, waited 15 seconds, and observed iOS remove the location icon from the status bar. Hope this helps somebody out there!
I was working with CLLocationManager in Swift and I think is relevant to the either Swift or Objective-C but, I just created a boolean which I update to true whenever I have received the location update. Since in my case I just need it once on launch.. Example,
// my boolean to stop location updates
var alreadyUpdatedLocation = Bool()
Also, in my case I have created a helper function that whenever I get the data/location of the user, I just call my own stopUpdatingLocation like this,
// helper function to stop updates
func stopUpdationgLocation() {
// since I received my data within a block, I don't want to just return whenever it wants to :)
dispatch_async(dispatch_get_main_queue()) {
// the building stop updating location function call
self.locationManager.stopUpdatingLocation()
// my own trick to avoid keep getting updates
self.alreadyUpdatedLocation = true
}
}
Then, where ever you use the location updates that you have received, you could do this...
// avoiding multiple calls after I have received user location
if(self.alreadyUpdatedLocation) {
return
}
I hope it helps!
try this..
if ([CLLocationManager significantLocationChangeMonitoringAvailable])
{
[self.locationManager startMonitoringSignificantLocationChanges];
}
[[self locationManager] stopUpdatingLocation];
If you are using the GoogleMaps SDK for iOS, I found that if you call
locationManager.stopUpdatingLocation()
and still have
mapView.isMyLocationEnabled = true
then the gps icon remains.
What I chose to do is initially show the user's location on the map and then turn it off after 8 seconds. This worked for me using the GoogleMaps SDK. I added this in ViewDidLoad:
DispatchQueue.main.asyncAfter(deadline: .now() + 8.0, execute: {
self.locationManager.stopUpdatingLocation()
self.mapView.isMyLocationEnabled = false
})
You could put the same code in viewWillDisappear if you prefer to not have the gps icon in the status bar when you segue to another view.
Problem:
In my case I use both startMonitoringSignificantLocationChanges and startUpdatingLocation.
Even after stopping the location through locationManager.stopMonitoringSignificantLocationChanges() &
locationManager.stopUpdatingLocation().
My location is getting called continuously.
Solution:
1. Check whether you have invalidated the timers.
2. Initialize locationManager.delegate = nil.
These will surely solve your problem.