CoreLocation manager not updating locations - ios

I was trying to implement a separate class for managing my location. I wanted to get my location whenever I click a button.
gpsFilter.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface gpsFilter : NSObject <CLLocationManagerDelegate>
#property (nonatomic, retain) CLLocationManager *gpsManager;
#property (nonatomic, retain) NSString * latitude;
#property (nonatomic, retain) NSString * longitude;
#end
gpsFilter.m.
#import "gpsFilter.h"
#implementation gpsFilter
- (id) init{
self = [super init];
if(self != nil){
self.gpsManager = [[CLLocationManager alloc] init];
self.gpsManager.delegate = self;
[self.gpsManager startUpdatingLocation];
BOOL enable = [CLLocationManager locationServicesEnabled];
NSLog(#"%#", enable? #"Enabled" : #"Not Enabled");
}
return self;
}
- (void)gpsManager:(CLLocationManager *) manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if(currentLocation != nil){
self.latitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
self.longitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}
- (void)gpsManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
}
#end
I am using a separate class because I wanted to add smoothing filter in the future. I don't get any updates. The NSLog is never triggered. I think some variable is getting autoreleased, but I am not sure, which one.
The viewController code is as follows.
#import "gpstestViewController.h"
#interface gpstestViewController (){
}
#end
#implementation gpstestViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.location = [[gpsFilter alloc] init];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)getloca:(id)sender {
self.latitudeLabel.text = [self.location latitude];
self.longitudeLabel.text = [self.location longitude];
}
- (IBAction)getLocation:(id)sender {
self.latitudeLabel.text = [self.location latitude];
self.longitudeLabel.text = [self.location longitude];
}
#end
I am sorry that I am dumping a lot of code, but I am a newbie to ios programming and I am not able to find what the problem is.
EDIT: The updateLocation delegate method is not being called at all.

The delegate methods must be named locationManager:didUpdateToLocation:fromLocation: and locationManager:didFailWithError:.
You cannot use custom method names like gpsManager:didUpdateToLocation:fromLocation:.
Also note that locationManager:didUpdateToLocation:fromLocation: is deprecated as of iOS 6 and you should use locationManager:didUpdateLocations:.

The signature of your didUpdateToLocation is wrong:
This is my code:
/** Delegate method from the CLLocationManagerDelegate protocol. */
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// here do
}
Further set the desiredAccuracy to CLLocationAccuracyBest.

Related

Objective-C issues with location services

I am trying to make a simple app the will get the users longitude and latitude
I followed the tutorial here:
http://www.appcoda.com/how-to-get-current-location-iphone-user/
and came with this:
.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet UILabel *longitudeLabel;
#property (strong, nonatomic) IBOutlet UILabel *latitudeLabel;
- (IBAction)getCurrentLocation:(id)sender;
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
{
CLLocationManager *locationManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
locationManager = [[CLLocationManager alloc] init];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)getCurrentLocation:(id)sender {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
_longitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
_latitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}
#end
My issue is that "Would like to use your current location" popup.
and none of the delegate methods are being hit, at all. I put a break point at the beginning of each delegate method and nothing. Please help.
Please ensure you have following keys in your info.plist:
NSLocationAlwaysUsageDescription with value I need Location
NSLocationWhenInUseUsageDescription with value I need Location
privacy - location usage description with value I need Location
Ensure the info.plist details as answered earlier and then add the below code during your initialization;
if (IS_OS_8_OR_LATER) {
[locationmanager requestWhenInUseAuthorization];
//or (as per your app requirement)
[locationmanager requestAlwaysAuthorization];
}

iOS CLLocationManagerDelegate didUpdateToLocation is not being called

I'm creating an app that uses core location and this is my code:
the .h :
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController
<CLLocationManagerDelegate>
#property(strong,nonatomic) CLLocationManager *manager;
#end
the .m :
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize manager;
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (!self.manager)
{
self.manager=[CLLocationManager new];
}
self.manager.delegate = self;
self.manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
[self.manager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation * currentLocation = (CLLocation *)[locations lastObject];
NSLog(#"Location: %#", currentLocation);
if (currentLocation != nil)
{
NSLog([NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude]);
NSLog([NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude]);
}
}
#end
the problem is didUpdateToLocation is not being called.
I tried putting a breakpoint inside of it and nothing happened.
For iOS location tracking to work correctly, here are the prerequisites, and the order is of importance, too:
Define your class as CLLocationManagerDelegate.
Instantiate CLLocationManager instance.
Set its delegate to self.
Set its various properties (accuracy etc)
Call [CLLocationManagerDelegate startUpdatingLocation] when you intend to.
Listen to location updates within your delegate method didUpdateLocations, implemented within the class designated as CLLocationManagerDelegate.
With your code, here are the things you need to correct:
-(IBAction)submit
{
[self.manager startUpdatingLocation];
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (!self.manager)
{
self.manager=[CLLocationManager new];
}
self.manager.delegate = self;
self.manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
In short, before telling it to start updating location, you need to instantiate it and set its properties right. Currently you are doing it the reverse way.
UPDATE
Also, your delegate method didUpdateToLocation is deprecated since iOS 6. You must replace it with newer method, like this:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation * currentLocation = (CLLocation *)[locations lastObject];
NSLog(#"Location: %#", currentLocation);
if (currentLocation != nil)
{
self.latitude.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
self.longitude.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
}
}
You need to add these keys to your Info.plist:
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
And also request for the type you want to authorise if iOS8:
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
So the system will display the alert "Allow "app" to access your location...? Allowing will start your location manager and didUpdateLocations will be called.

Is it necessary to use a singleton CLLocationManager to avoid waiting for the device location to update?

I've heard time and time again that there is always a better pattern than the singleton, but I can't understand how else my application could access the device location without waiting for the GPS to return data (I'm assuming that the location system is only running when explicitly called for, correct me if wrong).
So is there a better pattern for accessing CLLocation data from multiple (unrelated) controllers? Or can I expect the device location to be updating in the background even if I am not accessing it through a CLLocationManager?
Declare a single class . Like the following .
MyLocation.h
#protocol MyCLControllerDelegate <NSObject>
- (void)locationUpdate:(CLLocation *)location;
- (void)locationError:(NSError *)error;
#end
#interface MyLocation : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
id delegate;
}
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) id <MyCLControllerDelegate> delegate;
MyLocation.m
#import "MyLocation.h"
#implementation MyLocation
#synthesize locationManager;
#synthesize delegate;
- (id) init {
self = [super init];
if (self != nil) {
if([CLLocationManager locationServicesEnabled]) {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted )
{
[self showAlertWithTitle:#"Warning" andWithMessage:#"Determining your current location cannot be performed at this time because location services are enabled but restricted" forTargetView:self];
NSlog(#"Determining your current location cannot be performed at this time because location services are enabled but restricted");
}
else
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self; // send loc updates to myself
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kThresholdDistance];
[self.locationManager startUpdatingLocation];
NSLog(#"Location sharing set ON!");
}
} else {
[MobileYakHelper showAlertWithTitle:#"Error" andWithMessage:#"Determining your current location cannot be performed at this time because location services are not enabled." forTargetView:self];
NSLog(#"Location sharing set OFF!");
}
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSDictionary *dictValue = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithDouble:newLocation.coordinate.latitude], #"latitude",
[NSNumber numberWithDouble:newLocation.coordinate.longitude], #"longitude",
nil];
[[NSUserDefaults standardUserDefaults] setValue:dictValue forKey:#"MY_LOCATION"];
CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
if (meters >= kThresholdDistance ) {
[self.delegate locationUpdate:newLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
[self.delegate locationError:error];
}
#end
To use it in few controller .Adapt delegate in it's .h file and use like as follows :
- (void) initializeLocations
{
MyLocation _myLocation = [[MyLocation alloc] init];
_myLocation.delegate = self;
_myLocation.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
CLLocation * currentLocation = _myLocation.locationManager.location;
// Updating user's current location to server
[self sendUserCurrentCoordinate:currentLocation.coordinate];
// start updating current location
_myLocation.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[_myLocation.locationManager startUpdatingLocation];
[_myLocation.locationManager startUpdatingLocation];
}
- (void)locationUpdate:(CLLocation *)location {
NSLog(#"location %#", location);
}
- (void)locationError:(NSError *)error {
NSLog(#"locationdescription %#", [error description]);
}

UIlabel doesn't update user current speed

been having this problem for a few days now and can't seem to find a solution for it. It's probably some very basic stuff but still can't come up with a solution. So I'm trying to have my uilabel update a user speed in a car or on bike. But When the UIlabel update, it doesn't update the correct value. Any help will be appreciated.
Heres my .h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate, NSObject>
{
AppDelegate *appDelegate;
IBOutlet MKMapView *userMap;
CLLocationManager *locationManager;
}
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property(nonatomic) int speedCount;
#property (nonatomic,retain) CLLocationManager *locationManager;
#property (nonatomic, strong) WEPopoverController *popoverController;
+ (NSString *) speedToMPH: (float) value;
- (IBAction)btnMenuTapped:(id)sender;
#end
and my .h file
#implementation MainViewController
#synthesize speedCount;
#synthesize speedView;
#synthesize popoverController;
#synthesize locationManager;
- (void)locationError:(NSError *)error {
speedView.text = [error description];
}
-(void)viewWillAppear:(BOOL)animated
{
[userMap setRegion:MKCoordinateRegionMakeWithDistance(userMap.userLocation.coordinate, 5, 5) animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = [[UIApplication sharedApplication] delegate];
locationManager =[[CLLocationManager alloc] init];
// Do any additional setup after loading the view, typically from a nib.
[userMap setCenterCoordinate: userMap.userLocation.coordinate animated: YES];
[self performSelector:#selector(checkForLogin) withObject:nil afterDelay:1];
[self startLocationServices];
// create LM
self.locationManager = [CLLocationManager new];
// set its delegate
[self.locationManager setDelegate:self];
// set configuration
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
// start location services
[self.locationManager startUpdatingLocation];
// create an oldLocation variable if one doesn't exist
}
- (void)startLocationServices
{
// create the Location Manager
if (self.locationManager == nil) {
self.locationManager = [CLLocationManager new];
}
// stop services
[self.locationManager stopUpdatingLocation];
[self.locationManager setDelegate:nil];
self.speedView.text = #"Location Services stopped.";
}
// locationManager didUpdateToLocation FromLocation
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(#"%#", newLocation);
self.speedView.text = [NSString stringWithFormat:#"%d %.f ", speedCount, [newLocation speed]];
}
+ (NSString *) speedToMPH: (float) value
{
NSString *speedCount = #"0.0 ";
if (value>0) {
float mile = 1609.344f;
float mph = value / mile * 3600;
speedCount = [NSString stringWithFormat: #"%.f ", mph];
}
return speedCount;
}
CLLocation returns the speed in meters per second. So you will have to convert it to miles per hour by multiplying the value with 2.23694.
self.speedView.text = [NSString stringWithFormat:#"%d %.f ", speedCount, [newLocation speed] * 2.23694];

CLLocationManager not calling delegate in an NSObject

I'm trying to create a helper class to get the coordinates of the phone in any other class easily. I've followed a tutorial in which the UIViewController implemented the <CLLocationManagerDelegate> and it worked. I tried to do the same in a simple NSObject, but then my delegate was not called anymore.
This is the code I have :
PSCoordinates.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface PSCoordinates : NSObject <CLLocationManagerDelegate>
#property (nonatomic, retain) CLLocationManager* locationManager;
#end
PSCoordinates.m
#import "PSCoordinates.h"
#implementation PSCoordinates
- (id) init {
self = [super init];
if (self) {
self.locationManager = [[CLLocationManager alloc] init];
if ([CLLocationManager locationServicesEnabled])
{
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 100.0f;
NSLog(#"PSCoordinates init");
[self.locationManager startUpdatingLocation];
}
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"Géolocalisation : %#",[newLocation description]);
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"Géolocalisation (erreur) : %#",[error description]);
}
#end
I'm calling it by calling
PSCoordinates * coordinates = [[PSCoordinates alloc] init];
when pressing a button. The init is working as I can see the NSLog PSCoordinates init.
I've found other topics of people having the same problem but none of the answer solved it.
Your help would be really appreciated.
Make "PSCoordinates * coordinates" as global in your class. It will work :)

Resources