CLLocationManager startUpdatingLocation not working - iphone

So now I'm at least getting callbacks with the following code...
- (void)viewDidLoad {
[super viewDidLoad];
mapView=[[MKMapView alloc] initWithFrame:self.view.frame];
//mapView.showsUserLocation=TRUE;
mapView.delegate=self;
[self.view insertSubview:mapView atIndex:0];
NSLog(#"locationServicesEnabled: %#", [CLLocationManager locationServicesEnabled] ? #"YES":#"NO");
CLLocationManager *newLocationManager = [[CLLocationManager alloc] init];
[newLocationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[newLocationManager setDistanceFilter:kCLDistanceFilterNone];
[self setLocationManager:newLocationManager];
[[self locationManager] setDelegate:self];
[[self locationManager] startUpdatingLocation];
NSLog(#"Started updating Location");
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"Did update to location");
mStoreLocationButton.hidden=FALSE;
location=newLocation.coordinate;
MKCoordinateRegion region;
region.center=location;
MKCoordinateSpan span;
span.latitudeDelta=0.01;
span.longitudeDelta=0.01;
region.span=span;
[mapView setRegion:region animated:TRUE];
}
I can set breakpoints in the second method and NSLog is reporting continual location updates, but for some reason the zoom with span isn't working. Any idea why? It's got my coordinates and everything. Sort of scratching my head on this one.

Assign the CLLocationManager to a (strong) property on your class. (I assume you're using ARC BTW.) Right now the CLLocationManager doesn't live past the end of the viewDidLoad method, so it won't get to call your delegate method either.

Make sure that you've added <CLLocationManagerDelegate> in the #interface file.
Edit:
If the delegate is set properly, make sure you're using your locationManager property:
In the .h file:
#property (nonatomic, strong) CLLocationManager *locationManager;
In viewDidLoad:
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager startUpdatingLocation];

I think, You can make this work by two ways:
Using CLLocation framework
Check that, you have adopted the ViEWController with CLLocationManagerDelegate methods
#import<MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <CLLocationManagerDelegate,
MKMapViewDelegate>
{
CLLocationCoordinate2D location;
MKMapView *mapView;
}
#end
In ViewController.m:
#implementation GSViewController
- (void)viewDidLoad {
[super viewDidLoad];
mapView=[[MKMapView alloc] initWithFrame:self.view.frame];
mapView.showsUserLocation=TRUE;
mapView.delegate=self;
[self.view insertSubview:mapView atIndex:0];
CLLocationManager *locationManager=[[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(#"new location: %#", newLocation);
location=newLocation.coordinate;
MKCoordinateRegion region;
region.center=location;
MKCoordinateSpan span;
span.latitudeDelta=0.01;
span.longitudeDelta=0.01;
region.span=span;
[mapView setRegion:region animated:TRUE];
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"error: %#", error.description);
}
#end
2.Using the same MKMapKit framework
You can do this by using the MKMapViewDelegate method named didUpdateUserLocation:
Here you don't need the CLLocaionManager,
This will be done by:
In ViewController.h:
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController < MKMapViewDelegate>
{
CLLocationCoordinate2D location;
MKMapView *mapView;
}
#end
and In ViewController.m file:
#implementation GSViewController
- (void)viewDidLoad {
[super viewDidLoad];
mapView=[[MKMapView alloc] initWithFrame:self.view.frame];
mapView.showsUserLocation=TRUE;
mapView.delegate=self;
[self.view insertSubview:mapView atIndex:0];
}
-(void)mapView:(MKMapView *)mapV didUpdateUserLocation:(MKUserLocation *)userLocation
{
NSLog(#"map new location: %f %f", userLocation.coordinate.latitude, userLocation.coordinate.longitude);
location=userLocation.coordinate;
MKCoordinateRegion region;
region.center=location;
MKCoordinateSpan span;
span.latitudeDelta=0.1;
span.longitudeDelta=0.1;
region.span=span;
[mapV setRegion:region animated:TRUE];
}
#end

Well, first of all, you can never be sure that the location manager is able to update the location in the first place. There could be an error during update or you don't have access to the user's location.
Implement this CLLocationManager delegate method and verify the error.
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
"Implementation of this method is optional. You should implement this method, however."

If you're running this in the simulator only you might need to prompt it to change coordinates. In Xcode there is a bar above the debug output pane with the typical Location Services arrow. Next to that is a drop down list of locations. Once your app is running, switch the location it is simulating and see if that change triggers your code. Then test it on a real device.

In my case, it didn't enter on didChangeAuthorization. I was trying on a real device.
I deleted the application from the phone and install it again. And it works!
Hope this helps someone :)

For Swift 3
The method has changed to:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
from:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]!)
Notice the '_' and the cast of 'locations' to [CLLocation] rather than [AnyObject]!
If you use the old method it will never be called and you won't receive a warning that it has changed.

Related

"StopUpdatingLocation" is called but GPS Arrow doesnt disappear

I don´t understand why the gray gps arrow don´t disappear after stopUpdatingLocation is called. Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
if (self.locationManager == nil)
{
self.locationManager = [[[CLLocationManager alloc] init]autorelease];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
}
CLLocation *location = [self.locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
g_lat = coordinate.latitude;
g_lng = coordinate.longitude;
[self.locationManager startUpdatingLocation];
}
And here ist my didUpdateLocation:
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"Core location has a position.");
CLLocationCoordinate2D coordinate = [newLocation coordinate];
global_lat = coordinate.latitude;
global_lng = coordinate.longitude;
[self.locationManager stopUpdatingLocation];
}
- (void) locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"Core location can't get a fix.");
}
I also checked if any other app is using GPS!
After 20 minutes the Arrow is still there....
Thanks for help!
EDIT:
I think i missed something very important, on my first view after the App is started there is a Google Map! This is my Code:
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:g_lat
longitude:g_lng
zoom:15];
self.mapView = [GMSMapView mapWithFrame:CGRectMake(1.0f, 160.0f, 320.0f, 100)
camera:camera];
self.mapView.delegate = self;
self.showsUserLocation = YES;
self.mapView.trafficEnabled = YES;
self.mapView.myLocationEnabled = YES;
self.mapView.settings.myLocationButton = YES;
self.mapView.settings.compassButton = YES;
[self.mapView setUserInteractionEnabled:YES];
[self.mapView setCamera:camera];
[self.containerView addSubview:self.mapView];
Is it possible that the google map is updating all the time? If Yes, how can i stop that?
Regarding the google map: do you turn off the myLocationEnabled field when you push the new view controller? If not, then that can keep the GPS running. You can try it by not starting the GPS on the next view controller. If the GPS stays on, then the map is holding it.
Side note: This can be part of the normal operation. If your app stops receiving the location updates, then you are doing fine. iOS is doing lots of optimizations and leaving the GPS on for some time is probably part of this. During testing I saw that the arrow usually stays on for a while even if the app is killed from XCode.

iOS set ViewController and AppDelegate as listeners to CoreLocation model class

How do you set up the AppDelegate and a ViewController to be listeners to a model corelocation class? What are the proper design choices??
I'm interested in having a model class to implement CoreLocation and location updates. I'm guessing this class should be a sharedSingleton, because both my AppDelegate and ViewController wish to access it.
When my viewController calls it, I want the CLLocationManager to use startUpdatingLocation.
When the app goes into background, I want to monitor location updates in the AppDelegate using startMonitoringSignificantLocationChanges.
My question is, how do I set up the model class to handle these different types of location updates, as well as notify the ViewController or AppDelegate that a new location is found? Using NSNotification? Delegation doesn't seem to work because it's a one-to-one relationship.
Appreciate your help on figuring out how to design this.
Thanks!
You can have locationManager in the AppDelagete. And let the app delegate handle for you the location updates for all the application.
AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate,CLLocationManagerDelegate...> {
...
CLLocationManager* locationManager;
CLLocationCoordinate2D myLocation;
...
}
#property(nonatomic) CLLocationCoordinate2D myLocation;
...
#end
AppDelegate.m
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
...
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[locationManager startMonitoringSignificantLocationChanges];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
myLocation = newLocation.coordinate;
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateControlersThatNeedThisInfo" object:nil userInfo:nil];
}
...
In your controller:
ViewController.m
...
- (void)viewDidAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourFunction) name:#"updateControlersThatNeedThisInfo" object:nil];
}
-(void)yourFunction{
AppDelegate *app = [[UIApplication sharedApplication] delegate];
CLLocation myLocation = app.myLocation;
if(app.applicationState == UIApplicationStateBackground)
//background code
else
//foreground code
...
}

Alert selection with mapview

In my app, I used core location & Mapkit framework with mapview. When wwe install the app,it shows me alert like " would like to use current location" by default without coding for the one time only. And if i select "don't allow", the map view is just shown blue background?? and if i select "ok" then it works fine.
Help me!
my code is follow:
Appdelegate.m
CLLocationManager *locationManager;
CLLocation *userLocation;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
[self createEditableCopyOfDatabaseIfNeeded];
//=========================================Location Manager
if(locationManager == nil)
locationManager =[[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy= kCLLocationAccuracyBest;
self.locationManager.distanceFilter= 5;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
//==========================================
}
-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(#"new location");
self.userLocation=newLocation;
NSLog(#"user llocation %f , %f",userLocation.coordinate.latitude,userLocation.coordinate.longitude);
[self.locationManager startMonitoringSignificantLocationChanges];
}
Mapview.h
{
IBOutlet MKMapView *map;
CLLocation *currentLocation;
NSString *specificLatitude;
NSString *specificLongitude;
MKCoordinateRegion region;
}
Mapview.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[APPDELEGATE.locationManager startUpdatingLocation];
}
- (void)viewWillAppear:(BOOL)animated
{
self.map.delegate = self;
// Ensure that you can view your own location in the map view.
[self.map setShowsUserLocation:YES];
}
-(void)viewDidAppear:(BOOL)animated{
currentLocation =APPDELEGATE.userLocation;
region.center = self.currentLocation.coordinate;
MKCoordinateSpan span;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.03;
region.span = span;
[map setRegion:region animated:TRUE];
[self searchPressed];
NSLog(#"Mapview %f %f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude
);
}
If you select "Don't Allow" then call this delegate.
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
//Do something
}
I haven't tried this but maybe you can test to see if it works.
For your view controller that displays your map view, try conforming to the UIAlertViewDelegate.
Then in the alert view delegate callback method, you can do whatever you want, if it works:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// you need to type the exact title of the alert popup
// button index starts from 0 (left most button), so if the are 2 buttons
// and "Don't allow" button is on the right, the button == 1 is that button
// the user tapped on
if([alertView.title isEqualToString:#"Type Exact Alert Title Here"] && buttonIndex == 1)
{
// do something
}
}

Getting Longitude and Latitude Values

I am trying to connect to GPS from my code. I am doing so according to this tutorial.
- (void)viewDidLoad {
[super viewDidLoad];
CLController = [[CoreLocationController alloc] init];
CLController.delegate = self;
[CLController.locMgr startUpdatingLocation];
}
- (void)locationUpdate:(CLLocation *)location {
locLabel.text = [location description];
}
- (void)locationError:(NSError *)error {
locLabel.text = [error description];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
The above code is placed in a view controller called GetMyLocationViewController, and I have another view controller called MainScreenViewController.
When the screen loads, the MainScreenViewController gets loaded, and I will need the GPS location to continue operations with this screen.
In the ViewDidLoad method of MainScreenViewController I wrote the following;
- (void)viewDidLoad {
[super viewDidLoad];
GetMyLocationViewController *getMyLocationViewController = [[GetMyLocationViewController alloc]initwithXib:nil bundle:nil];
[self.navigationController pushViewController:getMyLocationViewController Animation:YES];
// AND THEN I NEED TO ACCESS THE LONGITUDE AND LATITUDE VALUES
}
When the above code gets executed, the viewDidLoad method of MainScreenViewController gets executed, but not the locationUpdate method. The only way I could get the values of longitude and latitude is by the execution of locationUpdate method. So how can I get these values?
Do you tested in a device? xcode before the version 4.2 dont have a GPS simulator, because of that the method locationUpdate never call.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if([self.delegate conformsToProtocol:#protocol(CoreLocationControllerDelegate)]) { // Check if the class assigning itself as the delegate conforms to our protocol. If not, the message will go nowhere. Not good.
[self.delegate locationUpdate:newLocation];
}
}
Are you sure you are loading your GetMyLocationViewController? Your code only shows loading the MainScreenViewController, which, in its -viewDidLoad method, loads itself again, which would cause an infinite loop of loading and pushing MainScreenViewControllers.
UPDATE: That CoreLocationController class in the tutorial seems unnecessary. Rather that using it, make CLLocationManager a property of your GetMyLocationViewController. Make GetMyLocationViewController's -viewDidLoad method look like this:
-(void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
}
don't forget to import the CoreLocation library and implement the delegate methods.

Geolocation doesn't work even on device

I am struggling with geolocation on simulator, but recently, I have tested it directly on device (iPhone) but the same issue remains, here is what I got when my app finish launching and the code of geolocation suppose to give me my location on the map (remember the picture above is for my app on iPhone and not with the simulator) :
so for my code, my app actually have a lot of views, but concerning this function, I have worked on the appdelegate(.m and .h) and the view concerning of showing the location on the map (PositionActuelleViewController).
appdelegate.m :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
sleep(3);
// Override point for customization after application launch.
self.locationManager=[[[CLLocationManager alloc] init] autorelease];
if([CLLocationManager locationServicesEnabled]) {
self.locationManager.delegate=self;
self.locationManager.distanceFilter=100;
[self.locationManager startUpdatingLocation];
}
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
and in the same file after the dealloc method :
#pragma mark CLLocationManagerDelegate Methods
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
MKCoordinateSpan span;
span.latitudeDelta=0.2;
span.longitudeDelta=0.2;
MKCoordinateRegion region;
region.span=span;
region.center=newLocation.coordinate;
[viewCont.mapView setRegion:region animated:YES];
viewCont.mapView.showsUserLocation=YES;
viewCont.latitude.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.latitude];
viewCont.longitude.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.longitude];
}
my PositionActuelleViewController.m file :
#import "PositionActuelleViewController.h"
#implementation PositionActuelleViewController
#synthesize mapView;
#synthesize latitude;
#synthesize longitude;
-(IBAction)goBackToMenu {
[self dismissModalViewControllerAnimated:YES];
}
-(IBAction)goToRechercherView;
{
rechercherViewController.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:rechercherViewController animated:YES];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[mapView release];
[latitude release];
[longitude release];
[super dealloc];
}
#end
What am I missing here?
Does the delegate method -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation ever get called? Maybe if you uncomment self.locationManager.distanceFilter=100; it will work because according to docs, distanceFilter property defines the minimum distance (measured in meters) a device must move laterally before an update event is generated.