I'm trying to get the user location. I added the coreLocation framework, and implamented the start location method and the delegate.
The problem that the delegate function just doesn't fired.
LocationManager.h :
#interface LocationManager : NSObject<CLLocationManagerDelegate>
#property(strong,nonatomic)CLLocationManager *locationManager;
-(void)startLocaitonService;
#end
LocationManager.m :
#implementation LocationManager
-(void)startLocaitonService
{
_locationManager=[[CLLocationManager alloc]init];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
}
#end
I'm have a breakpoint in the delegate function but nothing happens
That delegate method was deprecated in iOS 6.0.
From the class reference:
Deprecation Statement
Use locationManager:didUpdateLocations: instead.
Related
I'm trying to make a region based reminder. I have a viewcontroller that pops up when I need to add the reminder. In that vc I select a region where I need to be reminded and then use startMonitoringForRegion method. I set the locationManager delegate to the AppDelegate so that the AppDelegate can respond to entering or exiting the region.
The problem is that the when I close the viewcontroller the delegate methods don't get called. What am I doing wrong?
Here is the code:
AddReminderVC
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:self.lastCenter radius:self.radius identifier:#"id"];
[self.locationManager startMonitoringForRegion:region];
AppDelegate
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"EXIT REGION");
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(#"ENTER REGION");
}
Note that the methods do get called when the AddReminderVC is still visible. Only when it gets dismissed the delegate methods don't work.
you have to instantiate the locationManager in your AppDelegate or write another Singleton class to hold the locationManager. If you set it in a viewController the arc will delete the object when there are no more references to it.
I'm trying to getting my current location exact according to my coordinates. I've implemented CLLocationManager in my viewController called myLocation.
My problem is, I'm getting not getting my co-ordinates for the first time, but when I again approach I got the coordinates. I'm unable to understand this problem that why this not appear for the first time.
I also tried to give a NSTimer to stoplocation but but still unable to get the result for the first time, every first time I getting a (null) value, and then getting the co-ordinates.
My Code:
#import <UIKit/UIKit.h>
#import <Corelocation/CoreLocation.h>
#interface myLocation : UITableViewController<CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#interface myLocation () {
CLLocationManager* _locationManager;
NSString * _lat;
NSString * _lng;
}
#end
#implementation myLocation
- (void)viewDidLoad
{
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[_locationManager requestWhenInUseAuthorization];
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
[_locationManager stopUpdatingLocation];
_lat =[NSString stringWithFormat:#"%f",location.coordinate.latitude];
_lng =[NSString stringWithFormat:#"%f",location.coordinate.longitude];
}
- (void)viewWillAppear:(BOOL) animated
{
NSLOG(#"%#",_lat);
NSLOG(#"%#",_lng);
}
Your coordinates aren't appearing yet when you attempt to print them in viewWillAppear: because the CLLocationManager hasn't had enough time to retrieve the first location yet. Wait until didUpdateLocations: is first called before attempting to utilize the device coordinates because didUpdateLocations: is where you'll be receiving those coordinates. I recommend deleting your attempt to print the coordinates code from your viewWillAppear and simply print them in didUpdateLocations: instead.
In the comments, the OP stated he wants to "refresh" the location during viewWillAppear. I suggest stopping the updates when the view disappears and restarting the updates as soon as the view reappears:
- (void)viewWillAppear:(BOOL) animated
{
[_locationManager startUpdatingLocation];
}
- (void)viewWillDisappear:(BOOL) animated
{
[_locationManager stopUpdatingLocation];
}
It takes some time for location services to start up and call your delegate method - This almost certainly won't happen before viewWillAppear is called if you are only starting location services in viewDidLoad. Also, the first time your app executes it has to wait for the user to grant permission.
You can examine the location property of your CLLocationManager to get the most recent location. If it is nil then no location has been determined (yet).
I'm trying to make an iOS7 app that uses the current location of the device. I'm using the iPhone simulator on my Mac, but I'm having some problems. Every time my view that the location manager is in appears, it prints out 0.000000 for both latitude and longitude, even after I've set a custom location (from simulator>debug>location).
Also, it seemed strange that the simulator didn't ask for permission to use current location when it opened the app. Anybody know what's going on here?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[super viewDidLoad];
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
_location = [locationManager location];
_coord.longitude = _location.coordinate.longitude;
_coord.latitude = _location.coordinate.latitude;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
_coord.longitude = _location.coordinate.longitude;
_coord.latitude = _location.coordinate.latitude;
printf("%f\n",self.coord.longitude);
printf("%f\n",self.coord.latitude);
}
You need to get the newLocation from the delegate method didUpdateLocationToLocation:fromLocation:. Also implement didFailWithError delegate method. It takes some time before you start getting updated locations, hence the delegate call.
The last location is usually cached, so it maybe wise to check location's timestamp and filter the old location out.
Edit:
This is the cleanest example I can provide. Start new project in Xcode, pick Single View application template, iPhone. Don't touch storyboard, just replace content of your ViewController.m with this and run in Simulator or device. If on Simulator, go to Debug and set some location and you will get coordinates in the console. I am also starting and stopping location updates when the view goes on or off screen.
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#interface ViewController () <CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#implementation ViewController
#pragma mark - Location Manager delegate methods
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if ([newLocation.timestamp timeIntervalSinceNow] >= -300.0) {
NSLog(#"updated location with latitude %f longitude %f", newLocation.coordinate.longitude, newLocation.coordinate.latitude);
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.locationManager startUpdatingLocation];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.locationManager stopUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if(error.code == kCLErrorDenied) {
// alert user
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Access to location services is disabled"
message:#"You can turn Location Services on in Settings -> Privacy -> Location Services"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
} else if(error.code == kCLErrorLocationUnknown) {
NSLog(#"Error: location unknown");
} else {
NSLog(#"Error retrieving location");
}
}
#pragma mark - Location Manager getter
- (CLLocationManager *)locationManager
{
if (!_locationManager) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
_locationManager.distanceFilter = 60.0;
}
return _locationManager;
}
#end
I am using CLLocationManager class. I have a simple class method for capturing the location
+(void)captureLocation{
mLocationManager = [[CLLocationManager alloc]init];
mLocationManager.delegate = (id<CLLocationManagerDelegate>)self;
mLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
[mLocationManager startUpdatingLocation];
}
and i have the delegate methods of CLLocationManager also
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
}
now i am trying to call this method in my viewDidLoad as
- (void)viewDidLoad
{
[super viewDidLoad];
[myclass captureLocation];
}
the method is getting called but the delegate methods are not getting called.
I have other class method also and from there if I try to call the method again the captureLocation method is getting called but the delegate methods are not called. Here is the other class method
+(void)initialize{
[self captureLocation];
}
please help me to find out why delegate methods are not getting called as I am new to this field. Thanks in advance.
Also know that CoreLocation permissions have changed with iOS 8. If you don't request the new permissions authorizations, CoreLocation doesn't do anything. It fails quietly because the delegate methods are never called.
I realize this question was asked in 2013, but if you are having a similar problem with the delegate methods not getting called, this article is extremely helpful:
http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
While the article is very detailed and long, the actual code fix can be as minor as this:
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
And you have to add a value to info.plist, which is the message to display in the permissions alert. See screen grab.
Key: NSLocationWhenInUseUsageDescription
Value: Location is required to find out where you are (You can change that to whatever you want)
You are setting the delegate of the CLLocationManager inside a class method (i.e. one prefixed by + rather than -). So, when you reference self within that class method, that's the class, not an instance of the class. So, you are trying to set the delegate to the class rather than an instance of the class.
That won't work. The delegate methods are instance methods, not class methods. (This is presumably why you had to use the CLLocationManagerDelegate cast when assigning the delegate.)
You must actually instantiate whichever class you've implemented the CLLocationManagerDelegate methods. If you don't want to tie that instance to a particular view controller, you could use a singleton pattern. Regardless, you can set the location manager's delegate to point to that instance of that class.
For example, if you wanted it to be a singleton:
// MyClass.h
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
+ (instancetype)sharedManager;
- (void)startCapture;
- (void)stopCapture;
#end
and
// MyClass.m
#import "MyClass.h"
#import <CoreLocation/CoreLocation.h>
#interface MyClass () <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#end
#implementation MyClass
+ (instancetype)sharedManager
{
static id sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (void)startCapture
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
}
- (void)stopCapture
{
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
// ...
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// ...
}
#end
And then,
- (void)viewDidLoad
{
[super viewDidLoad];
[[MyClass sharedInstance] startCapture];
}
Calling self in a + method set your delegate to nil as it means ClassName as in [[ClassName alloc] init].
you need to:
mLocationManager.delegate = mLocationManager
instead of
mLocationManager.delegate (id<CLLocationManagerDelegate>)self;
in ios6 locationManager:didUpdateToLocation:fromLocation: is deprecated so you need to add another method in your code ...
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// this method get called in ios7 .
}
In iOS -8 need to do some changes :
Please have a look into this :Get current location in iOS-7 and iOS-8
The following code results in null coordinates. The weird thing is the UIAlert prompting the app to use current location appears briefly before the user can select yes.
My code which i have used :
CLLocationManager *locationManager;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
float latitude = locationManager.location.coordinate.latitude;
float longitude = locationManager.location.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
The NSLog prints 0.0000000 for both coordinates.
Thanks!
The reason you're getting 0 is because the location manager hasn't collected any data at that point (it has started thought)
You need to set your class as the delegate of the location manager (ie supplying a function that is called whenever a new location is retrieved), and also retain your location manager.
// Inside .m file
#interface MyClass () <CLLocationManagerDelegate> // Declare this class to implement protocol CLLocationManagerDelegate
#property (strong, nonatomic) CLLocationManager* locationManager; // Retains it with strong keyword
#end
#implementation MyClass
// Inside some method
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
// Delegate method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation* loc = [locations lastObject]; // locations is guaranteed to have at least one object
float latitude = loc.coordinate.latitude;
float longitude = loc.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
}