CLLocationManager Use of undeclared identifier 'error' [closed] - ios

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Am setting up CLLocationManager to decipher error codes, but am getting an undeclared identifier 'error' which I have commented out.
Why is Xcode asking me to declare 'error' as an identifier? I thought that CLLocationManager would read in error codes and translate them into plain English?
What am I missing here?
CurrentLocationViewController.m
#import "CurrentLocationViewController.h"
#interface CurrentLocationViewController ()
#end
#implementation CurrentLocationViewController {
CLLocationManager *_locationManager;
CLLocation *_location;
BOOL _updatingLocation;
NSError *_lastLocationError;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if((self = [super initWithCoder:aDecoder])) {
_locationManager = [[CLLocationManager alloc] init];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self updateLabels];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)getLocation:(id)sender
{
[self startLocationManager];
[self updateLabels];
}
#pragma mark - CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError %#", error);
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *newLocation = [locations lastObject];
if (error.code == kCLErrorLocationUnknown) { // Use of undeclared identifier 'error'
return;
}
[self stopLocationManager];
_lastLocationError = error; // Use of undeclared identifier 'error'
[self updateLabels];
}
-(void)updateLabels
{
if (_location != nil) {
self.latitudeLabel.text = [NSString stringWithFormat:#"%.8f", _location.coordinate.latitude];
self.longitudeLabel.text = [NSString stringWithFormat:#"%.8f", _location.coordinate.longitude];
self.tagButton.hidden = NO;
self.messageLabel.text = #"";
} else {
self.latitudeLabel.text = #"";
self.longitudeLabel.text = #"";
self.addressLabel.text = #"";
self.tagButton.hidden = YES;
NSString *statusMessage;
if (_lastLocationError == nil) {
if ([_lastLocationError.domain isEqualToString:kCLErrorDomain] && _lastLocationError.code == kCLErrorDenied) {
statusMessage = #"Location Services Disabled";
} else {
statusMessage = #"Error Getting Location";
}
} else if (![CLLocationManager locationServicesEnabled]) {
statusMessage = #"Location Services Disabled";
} else if (_updatingLocation) {
statusMessage = #"Searching...";
} else {
statusMessage = #"Press the Button to Start";
}
self.messageLabel.text = statusMessage;
}
}
-(void)startLocationManager
{
if ([CLLocationManager locationServicesEnabled]) {
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[_locationManager startUpdatingLocation];
_updatingLocation = YES;
}
}
-(void)stopLocationManager
{
if (_updatingLocation) {
[_locationManager stopUpdatingLocation];
_locationManager.delegate = nil;
_updatingLocation = NO;
}
}
#end

Oh jeez. You're in over your head, aren't you?
It looks like you have 2 methods that deal with a variable called "error".
The first is locationManager:didFailWithError:
This method is the method the location manager will call if it detects an error state.
In that method, an NSError object is being passed in as "error". If you want to log/save the error that you get back, this is the place to do it. You should probably save the error to _lastLocationError here if you will need it later. It would also be a good idea to display the error to the user in this method.
The second method that tries to refer to a variable called "error" is locationManager:didUpdateLocations:
That method does not have "error" as a parameter. The variable name "error" is not meaningful here. You won't get error values here, and should not expect them.
It's likely that if your locationManager:didFailWithError: method is called, your locationManager:didUpdateLocations: method will never be called because the location manager already told you that there was a problem and it was not able to handle your request.

Related

iOS 11 - Location update not received after adding delegate

I have been having trouble with location services in iOS 11 for both "Allow while Use" and "Always Allow". Works without issue in iOS < 11. Followed this thread in trying to fix but still doesn't work. What am I missing? Thank you in advance.
I have UITabViewController in my app and a UINavigationController inside each tab.
I have a singleton LocationManager class. I'm setting my UINavigationController's RootViewController as delegate the ViewController's viewWillAppear to receive location updates and removing in viewWillDisappear.
Now, When I launch the app, before the tab bar is created, I can see the location update is being called in the LocationManager Class.
But when I add my UIViewController as delegate and give startUpdatingLocation I'm not receiving the location update in my UIVIewController.
Then I press Home button and exit the app. Again immediately launch the app and I get the location update in my delegate method.
I have added all three location authorization description in my Info.plist file.
Info.Plist:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Blah Blah Blah</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Blah Blah Blah</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Blah Blah Blah</string>
LocationController.m:
#import "LocationController.h"
//static int LOCATION_ACCESS_DENIED = 1;
//static int LOCATION_NETWORK_ISSUE = 2;
//static int LOCATION_UNKNOWN_ISSUE = 3;
enum {
LOCATION_ACCESS_DENIED = 1,
LOCATION_NETWORK_ISSUE = 2,
LOCATION_UNKNOWN_ISSUE = 3
};
static LocationController* sharedCLDelegate = nil;
#implementation LocationController
int distanceThreshold = 10.0; // in meters
#synthesize locationManager, currentLocation, locationObservers;
- (id)init
{
self = [super init];
if (self != nil) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = distanceThreshold;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
[self.locationManager startMonitoringSignificantLocationChanges];
self.locationManager.delegate = (id)self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization]; //I tried both commenting this line and uncommenting this line. Didn't make any difference
}
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
{
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
[self.locationManager startUpdatingHeading];
locationObservers = [[NSMutableArray alloc] init];
}
return self;
}
#pragma mark -
#pragma mark CLLocationManagerDelegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"locationManager didUpdateLocations = %#",locations);
CLLocation *newLocation = [locations lastObject];
if (newLocation.horizontalAccuracy < 0) {
return;
}
currentLocation = newLocation;
for(id<LocationControllerDelegate> observer in self.locationObservers) {
if (observer) {
// CLLocation *newLocation = [locations lastObject];
// if (newLocation.horizontalAccuracy < 0) {
// return;
// }
// currentLocation = newLocation;
NSTimeInterval interval = [currentLocation.timestamp timeIntervalSinceNow];
//check against absolute value of the interval
if (fabs(interval)<30) {
[observer locationUpdate:currentLocation];
}
}
}
}
- (void)locationManager:(CLLocationManager*)manager
didFailWithError:(NSError*)error
{
NSLog(#"locationManager didFailWithError: %#", error);
for(id<LocationControllerDelegate> observer in self.locationObservers) {
if (observer) {
[observer failedToGetLocation:error];
}
}
switch (error.code) {
case kCLErrorDenied:
{
break;
}
case kCLErrorNetwork:
{
break;
}
default:
break;
}
}
#pragma mark - Singleton implementation in ARC
+ (LocationController *)sharedLocationInstance
{
static LocationController *sharedLocationControllerInstance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedLocationControllerInstance = [[self alloc] init];
});
return sharedLocationControllerInstance;
}
-(void) locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
NSLog(#"didChangeAuthorizationStatus = %i",status);
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self.locationManager stopUpdatingLocation];
[self.locationManager startUpdatingLocation];
}
}
- (void) addLocationManagerDelegate:(id<LocationControllerDelegate>)delegate {
if (![self.locationObservers containsObject:delegate]) {
[self.locationObservers addObject:delegate];
}
[self.locationManager startUpdatingLocation];
}
- (void) removeLocationManagerDelegate:(id<LocationControllerDelegate>)delegate {
if ([self.locationObservers containsObject:delegate]) {
[self.locationObservers removeObject:delegate];
}
}
+ (id)allocWithZone:(NSZone *)zone {
#synchronized(self) {
if (sharedCLDelegate == nil) {
sharedCLDelegate = [super allocWithZone:zone];
return sharedCLDelegate; // assignment and return on first allocation
}
}
return nil; // on subsequent allocation attempts return nil
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
#pragma mark UIAlertViewDelegate Methods
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (alertView.tag) {
case LOCATION_ACCESS_DENIED:
{
if (buttonIndex == 1) {
//[[UIApplication sharedApplication] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs:root=LOCATION_SERVICES"]];
}
}
break;
case LOCATION_NETWORK_ISSUE:
break;
case LOCATION_UNKNOWN_ISSUE:
break;
default:
break;
}
[alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
}
#end
LocationController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>
// protocol for sending location updates to another view controller
#protocol LocationControllerDelegate
#required
- (void)locationUpdate:(CLLocation*)location;
- (void)failedToGetLocation:(NSError*)error;
#end
#interface LocationController : NSObject<CLLocationManagerDelegate,UIAlertViewDelegate>
#property (nonatomic, strong) CLLocationManager* locationManager;
#property (nonatomic, strong) CLLocation* currentLocation;
#property (strong, nonatomic) NSMutableArray *locationObservers;
+ (LocationController*)sharedLocationInstance; // Singleton method
- (void) addLocationManagerDelegate:(id<LocationControllerDelegate>) delegate;
- (void) removeLocationManagerDelegate:(id<LocationControllerDelegate>) delegate;
#end
ViewController.m
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"VC viewWillAppear");
[locationControllerInstance addLocationManagerDelegate:self];
}
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[LocationController sharedLocationInstance];
}
I had one of the new devices reported this problem, as you know the the Location Manager usually calls this:
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
The bizarre thing is that the UserLocation object contains two coordinate objects:
1) userLocation.location.coordinate: This used to work fine, but for some reason it's returning NULL on IOS11 on some devices (it's unknown yet why or how this is behaving since IOS11).
2) userLocation.coordinate: This is another (same) object as you can see from the properties, it has the location data and continues to work fine with IOS11, this does not seem to be broken (yet).
So, with the example above, "I guess" that your:
(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
Might be having the same problem (i.e. the array might be returning a NULL somewhere in the location object, but not the coordinate object, the solution I did on my code which gets one location at a time, is now fixed by by replacing userLocation.location.coordinate with userLocation.coordinate, and the problem gone away.
I also paste my function below to assist you further, hopefully it would help you to resolve yours too, notice that I have two conditions for testing one for sourcing the location object and the other for sourcing the coordinate object, one works fine now, and the other seems to be broken in IOS11:
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
Log (4, #"MapView->DidUpdateUL - IN");
if (_OrderStartTrackingMode == enuUserMapTrackingMode_User)
{
if (userLocation)
{
if (userLocation.location)
{
if ( (userLocation.location.coordinate.latitude) && (userLocation.location.coordinate.longitude))
{
[_mapLocations setCenterCoordinate:userLocation.location.coordinate animated:YES];
} else {
if ( (userLocation.coordinate.latitude) && (userLocation.coordinate.longitude))
{
[self ShowRoutePointsOnMap:userLocation.coordinate];
}
}
}
}
} else if (_OrderStartTrackingMode == enuUserMapTrackingMode_Route) {
if (userLocation)
{
if ( (userLocation.coordinate.latitude) && (userLocation.coordinate.longitude))
{
[self ShowRoutePointsOnMap:userLocation.coordinate];
}
}
}
Log (4, #"MapView->DidUpdateUL - OUT");
}
Needless to say, have you checked your settings for the Map object, you should have at least "User Location" enabled:
P.S. The Log function on the code above is a wrapper to the NSLog function, as I use mine to write to files as well.
Good luck Uma, let me know how it goes.
Regards, Heider

Inconsistent behaviour by proximity API - iOS iBeacon

I am converting an iOS device into iBeacon and then using core location' ranging API to detect beacon' proximity. Now, this works but I see an unpredictable behaviour where sometimes at a defined distance (say 10 meters away) I see No Beacon sometimes Far Beacon and some times Near Beacon.
Is there a way to make this behaviour more consistent?
- (void)viewDidLoad {
[super viewDidLoad];
self.beaconSwitch.on = NO;
self.beaconView.backgroundColor = [UIColor clearColor];
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
BeaconRegion *beaconRegion = [[BeaconRegion alloc] init];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconRegion.uuid major:[beaconRegion.major shortValue] minor:[beaconRegion.minor shortValue] identifier:beaconIdentifier];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.peripheralManager stopAdvertising];
}
- (IBAction)doneButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)beaconSwitchPressed:(id)sender {
if (self.beaconSwitch.on == true) {
self.beaconView.beaconState = BNBeaconStateBroadcasting;
NSDictionary *data = [self.beaconRegion peripheralDataWithMeasuredPower:nil];
[self.peripheralManager startAdvertising:data];
} else {
self.beaconView.beaconState = BNBeaconStateStop;
[self.peripheralManager stopAdvertising];
}
}
Here is how I am converting my iOS device into a beacon:
And here is how I am getting its proximity:
- (void)viewDidLoad {
[super viewDidLoad];
BeaconRegion *beaconRegion = [[BeaconRegion alloc] init];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconRegion.uuid identifier:beaconIdentifier];
self.beaconRegion.notifyOnEntry = YES;
self.beaconRegion.notifyOnExit = YES;
self.beaconRegion.notifyEntryStateOnDisplay = YES;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.detectionSwitch.on = NO;
}
- (IBAction)beaconDetectionSwitchPressed:(id)sender {
if (self.detectionSwitch.isOn) {
[self.locationManager startMonitoringForRegion:self.beaconRegion];
[self.locationManager requestStateForRegion:self.beaconRegion];
} else {
self.lastProximity = CLProximityUnknown;
[self.locationManager stopMonitoringForRegion:self.beaconRegion];
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
self.titleLabel.text = #"";
self.messageLabel.text = #"";
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.locationManager stopMonitoringForRegion:self.beaconRegion];
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
self.locationManager = nil;
}
- (void)locationManager:(CLLocationManager *)iManager didEnterRegion:(CLRegion *)iRegion {
NSLog(#"Detected a beacon");
if (![self.beaconRegion isEqual:iRegion]) {
return;
}
NSLog(#"Entered into the beacon region = %#", iRegion);
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
NSLog(#"Ranging beacon successful");
if (beacons.count > 0) {
CLBeacon *nearestBeacon = beacons[0];
CLProximity currentProximity = nearestBeacon.proximity;
if (currentProximity == self.lastProximity) {
NSLog(#"No Change in Beacon distance");
} else {
self.lastProximity = currentProximity;
[self updateUserAboutProximity];
}
} else {
self.lastProximity = CLProximityUnknown;
}
}
- (void)updateUserAboutProximity {
NSString *title = #"--";
NSString *message = #"--";
switch (self.lastProximity) {
case CLProximityUnknown:{
title = #"No Beacon";
message = #"There is no nearby beacon";
}
break;
case CLProximityImmediate:{
title = #"Immediate Beacon";
message = #"You are standing immediate to video wall!";
}
break;
case CLProximityNear:{
if (self.isServerCallOn) {
title = #"Near Beacon";
message = #"You are standing near to video wall!";
} else {
title = #"Near Beacon";
message = #"You are standing near to video wall! Initiating a server call.";
if (!self.ignoreSeverCallTrigger) {
self.isServerCallOn = YES;
[self talkToServer];
} else {
NSLog(#"Ignoring server call trigger");
message = #"Ignoring server call trigger!";
}
}
}
break;
case CLProximityFar:{
title = #"Far Beacon";
message = #"You are standing far from video wall!";
}
break;
default:
break;
}
self.titleLabel.text = title;
self.messageLabel.text = message;
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state == CLRegionStateInside) {
NSLog(#"Starting Ranging");
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (![CLLocationManager locationServicesEnabled]) {
NSLog(#"Location Service Not Enabled");
}
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways) {
NSLog(#"Location Service Not Authorized");
}
}
For now, I have put a condition on received signal strength indicator (rssi) value and accepting anything > -60 in Near proximity to make the distance little more predictable. So, within Nearby proximity also I trigger my action if rssi > -60.

How to get paired bluetooth devices

I want to create one application that show me paired devices in my app.(for example any device that paired me before detect and show me.)
also in the next time I want to send one NSString like "hello" to paired device.
I searching in google and I got so confused!!!
Please tell me first how to get paired device with my mobile and second how to send NSString value to them.
Here is an exemple for what you need :
You have to adapt it to match what u want. But you can see how it work ...
#implementation ViewController
{
CBPeripheralManager *_peripheralManager;
BOOL _isAdvertising;
}
- (void)_startAdvertising
{
NSUUID *estimoteUUID = [[NSUUID alloc] initWithUUIDString:#"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:estimoteUUID
major:2
minor:1
identifier:#"SimEstimote"];
NSDictionary *beaconPeripheralData = [region peripheralDataWithMeasuredPower:nil];
[_peripheralManager startAdvertising:beaconPeripheralData];
}
- (void)_updateEmitterForDesiredState
{
if (_peripheralManager.state == CBPeripheralManagerStatePoweredOn)
{
// only issue commands when powered on
if (_isAdvertising)
{
if (!_peripheralManager.isAdvertising)
{
[self _startAdvertising];
}
}
else
{
if (_peripheralManager.isAdvertising)
{
[_peripheralManager stopAdvertising];
}
}
}
}
#pragma mark - CBPeripheralManagerDelegate
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
[self _updateEmitterForDesiredState];
}
#pragma mark - Actions
- (IBAction)advertisingSwitch:(UISwitch *)sender
{
_isAdvertising = sender.isOn;
[self _updateEmitterForDesiredState];
}
#end
This for monitoring :
#implementation AppDelegate
{
CLLocationManager *_locationManager;
BOOL _isInsideRegion; // flag to prevent duplicate sending of notification
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)options
{
// create a location manager
_locationManager = [[CLLocationManager alloc] init];
// set delegate, not the angle brackets
_locationManager.delegate = self;
NSUUID *estimoteUUID = [[NSUUID alloc] initWithUUIDString:#"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:estimoteUUID
identifier:#"Estimote Range"];
// launch app when display is turned on and inside region
region.notifyEntryStateOnDisplay = YES;
if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
[_locationManager startMonitoringForRegion:region];
// get status update right away for UI
[_locationManager requestStateForRegion:region];
}
else
{
NSLog(#"This device does not support monitoring beacon regions");
}
// Override point for customization after application launch.
return YES;
}
- (void)_sendEnterLocalNotification
{
if (!_isInsideRegion)
{
UILocalNotification *notice = [[UILocalNotification alloc] init];
notice.alertBody = #"Inside Estimote beacon region!";
notice.alertAction = #"Open";
[[UIApplication sharedApplication] scheduleLocalNotification:notice];
}
_isInsideRegion = YES;
}
- (void)_sendExitLocalNotification
{
if (_isInsideRegion)
{
UILocalNotification *notice = [[UILocalNotification alloc] init];
notice.alertBody = #"Left Estimote beacon region!";
notice.alertAction = #"Open";
[[UIApplication sharedApplication] scheduleLocalNotification:notice];
}
_isInsideRegion = NO;
}
- (void)_updateUIForState:(CLRegionState)state
{
ViewController *vc = (ViewController *)self.window.rootViewController;
if (state == CLRegionStateInside)
{
vc.label.text = #"Inside";
}
else if (state == CLRegionStateOutside)
{
vc.label.text = #"Outside";
}
else
{
vc.label.text = #"Unknown";
}
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
// always update UI
[self _updateUIForState:state];
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
{
// don't send any notifications
return;
}
if (state == CLRegionStateInside)
{
[self _sendEnterLocalNotification];
}
else
{
[self _sendExitLocalNotification];
}
}
#end
You can have the complete description at this adress :
http://www.cocoanetics.com/2013/11/can-you-smell-the-ibeacon/

kCLErrorDomain Code=8 "The operation couldn’t be completed.

Am starting to do reverse geocoding, and the _geocoder instance variable gets initialized OK, but no data gets passed to the _placemark object. Here is the error log:
2013-12-16 14:00:12.040 MyLocations[10555:70b] *** Going to geocode
2013-12-16 14:00:12.041 MyLocations[10555:70b] *** Found placemarks: (null), error: Error Domain=kCLErrorDomain Code=8 "The operation couldn’t be completed. (kCLErrorDomain error 8.)"
Am assuming that the locationManager:didFailWithError: method is getting called, but don't understand the error code.
Here is the code for CurrentLocationViewController.m
#import "CurrentLocationViewController.h"
#interface CurrentLocationViewController ()
#end
#implementation CurrentLocationViewController {
CLLocationManager *_locationManager;
CLLocation *_location;
BOOL _updatingLocation;
NSError *_lastLocationError;
CLGeocoder *_geocoder;
CLPlacemark *_placemark;
BOOL _performingReverseGeocoding;
NSError *_lastGeocodingError;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if((self = [super initWithCoder:aDecoder])) {
_locationManager = [[CLLocationManager alloc] init];
_geocoder = [[CLGeocoder alloc] init];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self updateLabels];
[self configureGetButton];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)getLocation:(id)sender
{
if(_updatingLocation) {
[self stopLocationManager];
} else {
_location = nil;
_lastLocationError = nil;
[self startLocationManager];
}
[self updateLabels];
[self configureGetButton];
}
#pragma mark - CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError %#", error);
if (error.code == kCLErrorLocationUnknown) {
return;
}
[self stopLocationManager];
_lastLocationError = error;
[self updateLabels];
[self configureGetButton];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *newLocation = [locations lastObject];
if ([newLocation.timestamp timeIntervalSinceNow] <- 5.0) {
return;
}
if (newLocation.horizontalAccuracy < 0) {
return;
}
if (!_performingReverseGeocoding) {
NSLog(#"*** Going to geocode");
_performingReverseGeocoding = YES;
[_geocoder reverseGeocodeLocation:_location completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"*** Found placemarks: %#, error: %#", placemarks, error);
_lastGeocodingError = error;
if (error == nil && [placemarks count] > 0) {
_placemark = [placemarks lastObject];
} else {
_placemark = nil;
}
_performingReverseGeocoding = NO;
[self updateLabels];
}];
}
}
-(void)updateLabels
{
if (_location != nil) {
self.latitudeLabel.text = [NSString stringWithFormat:#"%.8f", _location.coordinate.latitude];
self.longitudeLabel.text = [NSString stringWithFormat:#"%.8f", _location.coordinate.longitude];
self.tagButton.hidden = NO;
self.messageLabel.text = #"";
} else {
self.latitudeLabel.text = #"";
self.longitudeLabel.text = #"";
self.addressLabel.text = #"";
self.tagButton.hidden = YES;
NSString *statusMessage;
if (_lastLocationError == nil) {
if ([_lastLocationError.domain isEqualToString:kCLErrorDomain] && _lastLocationError.code == kCLErrorDenied) {
statusMessage = #"Location Services Disabled";
} else {
statusMessage = #"Error Getting Location";
}
} else if (![CLLocationManager locationServicesEnabled]) {
statusMessage = #"Location Services Disabled";
} else if (_updatingLocation) {
statusMessage = #"Searching...";
} else {
statusMessage = #"Press the Button to Start";
}
self.messageLabel.text = statusMessage;
}
}
-(void)configureGetButton
{
if (_updatingLocation) {
[self.getButton setTitle:#"Stop"
forState:UIControlStateNormal];
} else {
[self.getButton setTitle:#"Get My Location"
forState:UIControlStateNormal];
}
}
-(void)startLocationManager
{
if ([CLLocationManager locationServicesEnabled]) {
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[_locationManager startUpdatingLocation];
_updatingLocation = YES;
}
}
-(void)stopLocationManager
{
if (_updatingLocation) {
[_locationManager stopUpdatingLocation];
_locationManager.delegate = nil;
_updatingLocation = NO;
}
}
#end
kCLErrorDomain error 8 means Apple geoloc servers know nothing about the provided location. When doing reverse geocoding: lat/long has no address match, when forward geocoding: the address is not known to link to lat/long

CLLocationManager SignificantLocationChanges Force Refresh

I have an app that uses CLLocation manager and I need ability to force a location event to be delivered. Apple documentation states...
After returning a current location fix, the receiver generates update events only when a significant change in the user’s location is detected. For example, it might generate a new event when the device becomes associated with a different cell tower. It does not rely on the value in the distanceFilter property to generate events. Calling this method several times in succession does not automatically result in new events being generated. Calling stopMonitoringSignificantLocationChanges in between, however, does cause a new initial event to be sent the next time you call this method.
So I read that as I can call stopMonitoringSignificantLocationChanges and then startMonitoringSignificantLocationChanges and receive a location event, however, in practice this is not working. See code below (I've removed pieces so as to not disclose private reverse geo APIs). This is a wrapper class to combine reverse geo with CLLocationManager. In my demo app I am calling beginMonitoringSignificantChanges and then stopMonitoringSignificantChanges and I am only seeing -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations called when I change locations or when I first install the app, not when I stop and start. Any thoughts?
//
// TTGeoWrapper.m
// LocationManagementDemoApp
//
// Created by Kyle Jurick on 12/17/12.
// Copyright (c) 2012 Kyle Jurick. All rights reserved.
//
#import "TTGeoWrapper.h"
#import "OpenXML.h"
#implementation TTGeoWrapper
-(id)initWith//removed code
{
self = [super init];
if (self) {
//removed code
_transactionTimeout=30;
//removed code
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
authorizationStatus = [CLLocationManager authorizationStatus];
if (authorizationStatus != kCLAuthorizationStatusAuthorized) {
ableToMonitorLocation = false;
}
else
{
ableToMonitorLocation = true;
}
}
return self;
}
-(void)dealloc
{
locationManager.delegate = nil;
}
-(void)beginMonitoringSignificantChanges
{
//if (ableToMonitorLocation) {
[locationManager startMonitoringSignificantLocationChanges];
/*}
NSMutableDictionary *requestFailureUserInfo = [[NSMutableDictionary alloc] init];
[requestFailureUserInfo setValue:#"NOT AUTHORIZED" forKey:#"FAILURE REASON"];
[requestFailureUserInfo setValue:[NSString stringWithFormat:#"%d", authorizationStatus] forKey:#"FAILURE REASON"];
NSError *requestFailure = [[NSError alloc] initWithDomain:#"TTGeoWrapper" code:0 userInfo:requestFailureUserInfo];
[_delegate requestDidFail:requestFailure TTGeoWrapper:self];*/
}
-(void)stopMonitoringSignificantChanges
{
[locationManager stopMonitoringSignificantLocationChanges];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//per Apple documentation, the last item in the array is the most current location
//http://developer.apple.com/library/ios/#documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html
int latestPollIndex = locations.count-1;
CLLocation *location = [locations objectAtIndex:latestPollIndex];
_timeStamp = location.timestamp;
CLLocationCoordinate2D coordinate = [location coordinate];
[self updateLocationWithLatAsync:coordinate.latitude Long:coordinate.longitude];
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus: (CLAuthorizationStatus)status
{
if (status != kCLAuthorizationStatusAuthorized) {
ableToMonitorLocation = false;
}
authorizationStatus = status;
}
-(NSString *)updateLocationWithLatAsync:(float)latitude Long:(float)longitude;
{
webRequest = [ASIHTTPRequest requestWithURL:[[NSURL alloc] initWithString:_URL]];
[webRequest setDelegate:self];
[webRequest setTimeOutSeconds:_transactionTimeout];
[self buildPacketLat:latitude Long:longitude];
PostGUID = [self generateUuidString];
[self getPostResponseAsync];
return PostGUID;
}
-(NSString *)updateLocationWithLatSync:(float)latitude Long:(float)longitude
{
webRequest = [ASIHTTPRequest requestWithURL:[[NSURL alloc] initWithString:_URL]];
[webRequest setDelegate:self];
[webRequest setTimeOutSeconds:_transactionTimeout];
[self buildPacketLat:latitude Long:longitude];
PostGUID = [self generateUuidString];
[self getPostResponse];
return PostGUID;
}
-(void)buildPacketLat:(float)latitude Long:(float)longitude
{
//removed code
[webRequest appendPostData:[requestXML dataUsingEncoding:NSASCIIStringEncoding]];
}
- (NSString *)generateUuidString
{
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef str = CFUUIDCreateString(kCFAllocatorDefault, uuid);
NSString *uuidString = (__bridge NSString *)str;
CFRelease(uuid);
CFRelease(str);
return uuidString;
}
-(void)getPostResponse
{
NSLog(#"Beginning Synchronous POST");
[webRequest startSynchronous];
}
-(void)getPostResponseAsync
{
NSLog(#"Beginning Asynchronous POST");
[webRequest startAsynchronous];
}
-(void)cancelAsyncRequest
{
NSLog(#"Cancelling Asynchronous POST");
[webRequest cancel];
}
-(void)requestFinished:(ASIHTTPRequest *)request
{
OpenXML *geoResponse = [[OpenXML alloc] initWithData:[request responseData]];
_LocationToXMLString = [geoResponse openXMLToString];
_LocationToOpenXML = geoResponse;
//removed code
else
{
NSMutableDictionary *requestFailureUserInfo = [[NSMutableDictionary alloc] init];
//removed code
NSError *requestFailure = [[NSError alloc] initWithDomain:#"TTGeoWrapper" code:0 userInfo:requestFailureUserInfo];
[_delegate requestDidFail:requestFailure TTGeoWrapper:self];
}
}
-(void)requestFailed:(ASIHTTPRequest *)request
{
NSError *requestFailure = [request error];
[_delegate requestDidFail:requestFailure TTGeoWrapper:self];
}
#end
Apparently, this works only if you re-init CLLocationManager each time too. The documentation does not seem to support that, but my testing certainly does. If someone has a better answer, I would love to hear it.
You are right. Only a re-init of the CLLocationManager will cause the SignificantLocationChanges update for to occur. If you need a fresh location update, then why not use standard location service? Using the standard you also get a much more accurate fix.

Resources