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.
Related
In my app there's a button to add records to DataBase. Every time user tap that button, he adds a record to the DB. Part of that record should be the location of the user when he tapped the button.
So, in my code, when button is tapped, I invoke a method which track the user position. Trouble is that iPhone can't find immediately user's position so record is saved without coordinates (if I create another record around 10 seconds later everything works correctly).
Is there a way to track user only when he pushes the button and adding coordinates when available?
#property(nonatomic,strong) CLLocationManager *locationManager;
in ViewDidLoad
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate=self;
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
{
[self.locationManager requestAlwaysAuthorization];
}
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
Then
-(IBAction)button_Clicked:(id)sender
{
[self.locationManager startUpdatingLocation];
}
#pragma mark - Location Manager delegate
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations
{
CLLocation *location = [locations firstObject];
CLLocationCoordinate2D coordinate = location.coordinate;
}
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.
I'm trying to put everything location related inside a model. When I call this my MainViewController, the simulator doesn't ask me for my location, and nothing happens.
When I use the same code from my model, but put it directly in ViewDidLoad in my ViewController, everything works. I'm having a hard time understanding why.
Here is my model:
#implementation Location
{
CLLocationManager *_locationManager;
CLLocation *_location;
}
- (void)startLocationManager
{
NSLog(#"In startLocationManager");
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
_locationManager.delegate = self;
[_locationManager startUpdatingLocation];
}
#pragma mark - LocationManager Delegates
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"In didUpdateLocations");
if (locations) {
_location = [locations lastObject];
NSLog(#"%#", _location);
}
}
#end
I call this in my MainViewController like this:
- (void)viewDidLoad
{
[super viewDidLoad];
Location *location = [[Location alloc] init];
[location startLocationManager];
}
Why does the code work like a charm directly in the viewController, but not through my model?
I figured it out.
I needed to make location a property of your view controller instead of a local variable in the viewDidLoad. Otherwise it is created and deallocated within that method. I need it to live through the lifecycle of my view controller.
Hi I am implementing Location services in my app. First I have to know my Coordinates to get the distance between some places that I have in a list and the device. Then if I go into a place I can make a check in, so, I need to get coordinates again, and the problem is here. Second time I try to get coordinates, the method -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations is not called.. and I can not get new Coordinates.
My manager is located in a NSObject sublcass with this code:
(id)init {
if ( self = [super init] ) {
if ([CLLocationManager locationServicesEnabled])
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
}
return self;
}
-(void) checkLongLatitudeAgain {
[locationManager startUpdatingLocation];
}
#pragma mark Delegates de CLLocationManager
//
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"LON%f", manager.location.coordinate.longitude);
NSLog(#"LAT:%f", manager.location.coordinate.latitude);
NSTimeInterval howRecentNewLocation = [newLocationeventDate timeIntervalSinceNow];
if (manager.location.horizontalAccuracy <= 100.0 && howRecentNewLocation < -0.0 && howRecentNewLocation > -20.0){
//Usar coordenada
[self.delegate getLocationForCheckIn:manager.location];
[self stopUpdatingLocation:#"Fins"];
}
}
// ---------------------------------------------------------------------------------------------------------------------
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
//
if ([error code] != kCLErrorLocationUnknown) {
[self stopUpdatingLocation:NSLocalizedString(#"Error", #"Error")];
}
//
}
// ---------------------------------------------------------------------------------------------------------------------
- (void)stopUpdatingLocation:(NSString *)state {
//Detenemos la lectura del GPS
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
NSLog(#"Stop gps");
//
}
I call the class when the list of places is open, and also when inside a place the user press checkIn button. Both times I do it with this code:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
You are creating a new manager every time:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
That new manager is not assigned to any delegate.
You need to use the previous manager you have created and assigned to your delegate, something like:
[locationManager checkLongLatitudeAgain];
You can check the documentation at http://developer.apple.com - https://developer.apple.com/library/ios/documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html
In particular you can check the Starting the Standard Location Service and Starting the Significant-Change Location Service sections. You have to use the startMonitoringSignificantLocationChanges or startUpdatingLocation method of CLLocationManager, cache your location somewhere and update it only when a new location is received, otherwise like it is stated in the documentation: "If a location update has already been delivered, you can also get the most recent location data directly from the CLLocationManager object without waiting for a new event to be delivered".
i dont know why you are initiating your location manager again again, also even if you some how manage to solve current problem but it's not proper way of dealing with location manage based applications.I had been in trouble previously when i was working on location based app. the best approach for location based app is singleton.
apple forum discussion
you can find
this
and this very helpful.
just an advice, :)
Thanks.
In iOS8 for me I had to call [locationManager stopUpdatingLocation]; before calling [locationManager startUpdatingLocation] to start getting updates second time and it works for me.
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