CLLocationManager: didEnterRegion & didExitRegionAlert method did not called - iphone

I am using CLRegion for geofencing. I monitored CLCircularRegion set for notifyOnExit and notifyOnEntry.
Here is my code:
CLLocationCoordinate2D coordinateGYM = CLLocationCoordinate2DMake(lat,lng);
CLCircularRegion *regionSet = [[CLCircularRegion alloc]initWithCenter:coordinateGYM radius:RADIUS identifier:strTitle];
if(isExit)
{
regionSet.notifyOnExit = YES;
regionSet.notifyOnEntry = NO;
}
else
{
regionSet.notifyOnExit = NO;
regionSet.notifyOnEntry = YES;
}
[self.locationManager startMonitoringForRegion:regionSet];
[self.locationManager startUpdatingHeading];
Before monitor the region I try to removed all the region which motinored before it. Then I monitored with region. But it will directly invote
monitoringDidFailForRegion delegate method with Error: The operation couldn’t be completed. (kCLErrorDomain error 4.) error. And it will not called delegate method.
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
}
Can anyone help me what is error in my code?
Thanks,

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.

How to redirect to a view controller based on the status of location services in iOS

I'm using the following code to check to see if the user's location services for the app have changed. If they change they should view a different view controller. It really only needs to run each time the app launches and then redirect based on the [CLLocationManager authorizationStatus] status
the problem with my code is that everytime the location updates the segue is ran.
thanks for any help
- (void)locationUpdate:(CLLocation *)location {
//locLabel.text = [location description];
NSLog(#"auth status is %u", [CLLocationManager authorizationStatus]);
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) {
[self performSegueWithIdentifier: #"SegueOffersGPS" sender: self];
} else {
[self performSegueWithIdentifier: #"SegueOffersNoGPS" sender: self];
}
If you want to stop updating location then write below code
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[self.locationManger stopUpdatingLocation];
}

CLLocationManager delegates not working after initialization

I am trying to get the compass of the iphone to work using the rhomobile framework.
I already did the rhomobile part, created a working wrapper that calls native methods on the iphone, but I cant manage to get the events to work.
Locationmanager.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface locationController : NSObject <CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
#property (strong, nonatomic) CLLocationManager *locationManager;
- (id)init;
- (void)dealloc;
#end
Locationmanager.m
#import "Locationmanager.h"
#include "ruby/ext/rho/rhoruby.h"
//store the values
double gx, gy, gz, gth;
//init location
locationController *lc;
#implementation locationController
#synthesize locationManager;
- (id)init {
if (self = [super init]) {
self.locationManager = [[CLLocationManager alloc] init];
NSLog(#"%#", [CLLocationManager headingAvailable]? #"\n\nHeading available!\n" : #"\n\nNo heading..\n");
NSLog(#"%#", [CLLocationManager locationServicesEnabled]? #"\n\nLocation available!\n" : #"\n\nNo location..\n");
// check if the hardware has a compass
if ([CLLocationManager headingAvailable] == NO) {
// No compass is available. This application cannot function without a compass,
// so a dialog will be displayed and no magnetic data will be measured.
locationManager = nil;
UIAlertView *noCompassAlert = [[UIAlertView alloc] initWithTitle:#"No Compass!" message:#"This device does not have the ability to measure magnetic fields." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[noCompassAlert show];
[noCompassAlert release];
NSLog(#"\n***** ERROR *****\n No compass found !!!");
} else {
// setup delegate callbacks
locationManager.delegate = self;
// heading service configuration
locationManager.headingFilter = kCLHeadingFilterNone;
// location service configuration
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
//start location services
[locationManager startUpdatingLocation];
// start the compass
[locationManager startUpdatingHeading];
}
return self;
}
}
- (void)dealloc {
[super dealloc];
// Stop the compass
[locationManager stopUpdatingHeading];
[locationManager release];
}
// This delegate method is invoked when the location manager has heading data.
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)heading {
NSLog(#"\n\n***** New magnetic heading *****\n %f\n", heading.magneticHeading);
NSLog(#"\n\n***** New true heading *****\n %f\n", heading.trueHeading);
gx = heading.x;
gy = heading.y;
gz = heading.z;
gth = heading.trueHeading;
}
// This delegate method is invoked when the location managed encounters an error condition.
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if ([error code] == kCLErrorDenied) {
// This error indicates that the user has denied the application's request to use location services.
NSLog(#"\n ***** ERROR *****\n Location not allowed!");
[locationManager stopUpdatingHeading];
} else if ([error code] == kCLErrorHeadingFailure) {
NSLog(#"\n ***** ERROR *****\n Magnetic interference or something!");
}
}
#end
//ruby wrappers
void locationmanager_init(void) {
// make sure we can only start this method once
static bool started = false;
if(!started) {
// Initialize the Objective C accelerometer class.
lc = [[locationController alloc] init];
started = true;
}
}
void locationmanager_get_heading(double *x, double *y, double *z, double *th) {
NSLog(#"\n ***** DEBUGGER *****\n Getting heading x: %f, y: %f, z: %f, heading: %f", gx, gy, gz, gth);
*x = gx;
*y = gy;
*z = gz;
*th = gth;
}
I'm running the code on an iphone 4 with iOS 5.1, in the console I can see the debug messages of init, but I never see a debug message of the didUpdateHeading delegate. Anyone got a clue what I missed here?
UPDATE
I think I need to run my code in a background thread to get it working. Currently the locationmanager_init initializes + leaves the code, therefor its not active and the events are not fired.
Anyone got a simple solution initializing this in the background to keep it active?
UPDATE 2
Returned the id, used self = [super init] and still no fix :(
GitHub code
Initializes with locationmanager_init, retrieves data with locationmanager_get_heading
You have to init the CLLocationManager on the main thread, check this SO here, or run it from a thread with an active run loop, check this SO here, From Apple documentation:
Configuration of your location manager object must always occur on a thread with
an active run loop, such as your application’s main thread.
Make sure your locationController and the CCLocationManager inside it are alive past initialization, check here. I may be wrong here, but from your Github code, it seems that the *lc variable is getting released in the autorelease pool. Try giving it an extra retain.
lc = [[[locationController alloc] init] retain];
I guess this is the cause of your problem. If the object is released you wont get any updates.
Not related to the question but:
You should call [super dealloc] last but not first, check this SO here
Put the return statement in your init method before the last parenthesis, and not before the second last.
...
// start the compass
[locationManager startUpdatingHeading];
}
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateHeading:(CLHeading *)heading;
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error;
These are your instance methods not delegate methods.
check
https://developer.apple.com/library/mac/#documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html
Possibly this is not the solution to the overall problem, but your init method is missing a return statement:
- (id)init {
if (self = [super init]) {
// do your setup here
}
return self;
}

iPhone - Initial user location with CCLocationManager

I'm using that code running on an iPhone 4 :
- (id)init
{
self = [super initWithNibName:#"OfflineView" bundle:nil]; // ok, not perfect but for test, that works fine
if (self) {
self.locationMgr = [[CLLocationManager alloc] init];
self.locationMgr.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
self.locationMgr.distanceFilter = kCLDistanceFilterNone;
self.locationMgr.headingFilter = kCLHeadingFilterNone;
self.locationMgr.delegate = self;
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// do things
}
// triggered when showing the view, first call here after the init
- (void) start
{
self.view.hidden = NO;
[self.locationMgr startUpdatingLocation];
[self.locationMgr startUpdatingHeading];
}
but the delegate method is not triggered.
It's only triggered when the phone moves.
How may I init my process with a valid user location when the view appears, without asking my user to shake it phone and make a 100m run, before being able to do something ?
You could "prime" it by kicking the delegate method yourself once.
- (void) start
{
self.view.hidden = NO;
[self.locationMgr startUpdatingLocation];
[self.locationMgr startUpdatingHeading];
[self locationManager: self.locationMgr didUpdateToLocation: [self.locationMgr currentLocation] fromLocation: nil];
}
where do you call start:? you should be getting first fix without moving. It's an asynchronous call back so might take time.
Ideally you should be calling startUpdateLocation in the init/viewDidLoad and then read it in locationUpdate:
- (void)locationUpdate:(CLLocation *)location {
// Read location
}

Receiving CLLocation updates on a background thread

I am trying to implement a (non-concurrent) NSOperation for location updates using the iPhone SDK. The "meat" of the NSOperation subclass goes something like this:
- (void)start {
// background thread set up by the NSOperationQueue
assert(![NSThread isMainThread]);
if ([self isCancelled]) {
return;
}
self->locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = self->desiredAccuracy;
locationManager.distanceFilter = self->filter;
[locationManager startUpdatingLocation];
[self willChangeValueForKey:#"isExecuting"];
self->acquiringLocation = YES;
[self didChangeValueForKey:#"isExecuting"];
}
- (void)cancel {
if ( ! self->cancelled ) {
[self willChangeValueForKey:#"isCancelled"];
self->cancelled = YES;
[self didChangeValueForKey:#"isCancelled"];
[self stopUpdatingLocation];
}
}
- (BOOL)isExecuting {
return self->acquiringLocation == YES;
}
- (BOOL)isConcurrent {
return NO;
}
- (BOOL)isFinished {
return self->acquiringLocation == NO;
}
- (BOOL)isCancelled {
return self->cancelled;
}
- (void)stopUpdatingLocation {
if (self->acquiringLocation) {
[locationManager stopUpdatingLocation];
[self willChangeValueForKey:#"isExecuting"];
[self willChangeValueForKey:#"isFinished"];
self->acquiringLocation = NO;
[self didChangeValueForKey:#"isExecuting"];
[self didChangeValueForKey:#"isFinished"];
}
locationManager.delegate = nil;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
assert(![NSThread isMainThread]);
// ... I omitted the rest of the code from this post
[self stopUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)theError {
assert(![NSThread isMainThread]);
// ... I omitted the rest of the code from this post
}
Now, on the main thread I create an instance of this operation and add it to an NSOperationQueue. The start method gets called, however none of the -locationManager:... delegate methods get called. I don't get it why they never get called.
I did make the interface adhere to the <CLLocationManagerDelegate> protocol. I'm letting the NSOperationQueue manage the thread for this operation, so it should all be conforming to the CLLocationManagerDelegate documentation:
The methods of your delegate object are called from the thread in which you started the corresponding location services. That thread must itself have an active run loop, like the one found in your application’s main thread.
I am not sure what else to try for this to work. Maybe it's staring me in the face... Any help is appreciated.
Thanks in advance!
You are missing the "active run loop" part. At the end of your start method add: while (![self isCancelled])
[[NSRunLoop currentRunLoop] runUntilDate:someDate];