I've just updated to Xcode 6/iOS 8 SDK and my location service simulation in simulator started not working. It was fine before I updated (I'm currently unable to test on real device). Now, when I select a location for simulation, nothing happens. Delegate's -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations method is not called. I've restarted Xcode, cleaned the build folder, nothing changed. Why can this happen?
Since IOS 8 you need to ask for authorization before starting the CLLocationManager.
Are you calling one of these methods?
[self.locationManager requestWhenInUseAuthorization]; // For foreground access
[self.locationManager requestAlwaysAuthorization]; // For background access
If you have created the project before XCode 6, you probably also need to add the info.plist entry for the new permission.
For more details have a look at this post: Location Services not working in iOS 8
Add Below code in your method
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
Also add Below line at your info.plist file
Key:NSLocationWhenInUseUsageDescription value:Uses current location
Using Xcode 6.3.1 I have had the location selection stop updating. The fix was to run another project, select "Simulate location > Don't Simulate Location" then build the original project again to resume normal location setting.
- (void)startLocationUpdates{
geocoder = [[CLGeocoder alloc] init];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[locationManager requestWhenInUseAuthorization];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
}
// Reverse Geocoding
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
fullAddress = [NSString stringWithFormat:#"%#,%#,%#,%#",
placemark.thoroughfare,
placemark.locality,
placemark.administrativeArea,
placemark.country];
subtitleLocation = [NSString stringWithFormat:#"PostalCode::%#",
placemark.postalCode];
} else {
// NSLog(#"%#", error.debugDescription);
}
} ];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error{
NSLog(#"Cannot find the location.");
}
The other answers are correct, but I also had to reset the simulator before I could get a location, whereas it was working fine on a device. The app was initially installed on that simulator before iOS 8.
To reset your simulator :
https://stackoverflow.com/a/16195931
Related
I am using iOS8 and using the following code for getting longitude and latitude by GPS:
-(void)CurrentLocationIdentifier
{
locationManager = [CLLocationManager new];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 &&
[CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse)
//[CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways)
{
// Will open an confirm dialog to get user's approval
[locationManager requestWhenInUseAuthorization];
//[_locationManager requestAlwaysAuthorization];
} else {
[locationManager startUpdatingLocation]; //Will update location immediately
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
NSLog(#"lat%f - lon%f", location.coordinate.latitude, location.coordinate.longitude);
}
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined: {
NSLog(#"User still thinking..");
}
case kCLAuthorizationStatusDenied: {
NSLog(#"User hates you");
} break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways: {
[locationManager startUpdatingLocation]; //Will update location immediately
} break;
default:
break;
}
}
After running this code I am getting the output at log is : User still thinking. Can anyone help me with this I am new to iOS and CoreLocation.Framework ?
Please help me in finding the Error and how can I solve that.
Add this string in InfoPlist.strings files
1) NSLocationWhenInUseUsageDescription
2) NSLocationAlwaysUsageDescription
Try this code
locationManagerApp=[[CLLocationManager alloc] init];
locationManagerApp.delegate = self;
locationManagerApp.distanceFilter = kCLDistanceFilterNone;
locationManagerApp.desiredAccuracy = kCLLocationAccuracyHundredMeters;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[locationManagerApp requestAlwaysAuthorization];
}
[locationManagerApp startUpdatingLocation];
CLLocation *location1 = [locationManagerApp location];
CLLocationCoordinate2D coordinate = [location1 coordinate];
self.latValue= [NSString stringWithFormat:#"%f", coordinate.latitude];
self.longValue = [NSString stringWithFormat:#"%f", coordinate.longitude];
NSLog(#"Latitude = %#", self.latValue);
NSLog(#"Longitude = %#", self.longValue);
And run project in device.
In iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start. There are two Info.plist keys for the new location authorization. One or both of these keys is required. If neither of the keys are there, you can call startUpdatingLocation but the location manager won’t actually start. It won’t send a failure message to the delegate either (since it never started, it can’t fail). It will also fail if you add one or both of the keys but forget to explicitly request authorization.
So the first thing you need to do is to add one or both of the following keys to your Info.plist file:
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
Both of these keys take a string which is a description of why you need location services. You can enter a string like “Location is required to find out where you are” which, as in iOS 7, can be localized in the InfoPlist.strings file.
I want to get the current location latitude and longitude without using the map, is it possible to get like that, I am not getting that from searching the internet, can any one help me to find that.
I tried this with using the core location but even I am not got any thing.
please tell me how to find the latitude and longitude, thank you.
//remember to stop before you are done, either here or in view disappearance.
- (void) dealloc
{ [locationManager stopUpdatingLocation]; }
in .h file:
CLLocationManager *locationMgr;
in .m file:on load
locationMgr =[[CLLocationManager alloc] init];
locationMgr.desiredAccuracy = kCLLocationAccuracyBest;
locationMgr.delegate = self;
if ([locationMgr respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationMgr requestWhenInUseAuthorization];
}
[locationMgr startUpdatingLocation];
add following delegates:
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// Handle location updates
CLLocationCoordinate2D location=newLocation.coordinate;
float altitude = newLocation.altitude;
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
// Handle error
NSLog(#"error: %#",[error localizedDescription]);
}
may you are not authorising the location from user. thats why you are not getting anything
thanks
I have a code in a UIViewController that starts the location update:
[locationManager startUpdatingLocation];
Is working perfectly. But I need every time you exit this screen it stops updating the location and start again when I return.
The first time it for updates. In other times it does not stop.
Code for exit from view:
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
Ihave tried also: (without success too)
[locationManager stopMonitoringSignificantLocationChanges];
[locationManager stopUpdatingHeading];
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
locationManager = nil;
It always update. But from the second time not stop update.
didUpdateLocation code:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
[self addingMarkerUser];
}
You should put your code in the viewDidAppear and i suppose in your [self addingMarkerUser] you use something like this without the stop (if not, please provide the code) :
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:_currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (!(error)) {
//do something with the data.
//then stop the update.
[locationManager stopUpdatingLocation];
}
}];
If you do like that, every time your view appear, the location will start the update then stop once the data retrieve.
I identified a strange behaviour on my app using CoreLocation. I'm using the region monitoring functionality but, after authorising the location services (via popup or settings->Location Services) region monitoring fails (The operation couldn’t be completed. kCLErrorDomain error 5.). If I close the app and restart (therefore already authorised) everything works as expected.
My code looks like this:
-(void)initializeLocationServices
{
NSLog(#"Started location services");
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.pausesLocationUpdatesAutomatically = NO;
[locationManager startUpdatingLocation]; // to show authorisation popup
}
-(CLCircularRegion*)createRegion
{
// Test coordinates
CLLocationDegrees latitude = 50;
CLLocationDegrees longitude = -1;
CLLocationDistance radius = 50; // meters;
// If radius is too large, registration fails automatically, so limit the radius to the maximum value
if (radius > locationManager.maximumRegionMonitoringDistance) {
radius = locationManager.maximumRegionMonitoringDistance;
}
CLCircularRegion* region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(latitude, longitude) radius:radius identifier:#"TEST"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
NSLog(#"Created region");
return region;
}
-(void)monitorProximity
{
CLRegion *region = [self createRegion];
// Check if support is unavailable
if ( ![CLLocationManager isMonitoringAvailableForClass:[CLRegion class]]) {
NSLog( #"Failed to initialise region monitoring: support unavailable");
return;
}
// Check if authorised
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) {
NSLog( #"Failed to initialise region monitoring: app not authorized to use location services");
return;
} else {
NSLog(#"Started monitoring proximity");
}
// Clear out any old regions to prevent buildup.
if ([locationManager.monitoredRegions count] > 0) {
for (id obj in locationManager.monitoredRegions)
[locationManager stopMonitoringForRegion:obj];
}
[locationManager startMonitoringForRegion:region];
}
-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
NSLog(#"Started monitoring for region: %#", [region description]);
[locationManager requestStateForRegion:region]; // check if already inside region
}
-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
NSLog(#"Failed to start monitoring for region: %#", [error localizedDescription]);
}
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
NSLog(#"didDetermineState");
if (state == CLRegionStateInside) {
NSLog(#"inside");
return;
} else if (state == CLRegionStateOutside) {
NSLog(#"outside");
} else {
NSLog(#"unknown");
}
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(#"didEnterRegion");
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(#"didExitRegion");
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
NSLog(#"Monitoring authorisation status is now: %#", status == kCLAuthorizationStatusAuthorized ? #"authorized" : #"not authorized");
if (status == kCLAuthorizationStatusAuthorized) {
[self monitorProximity];
}
}
Am I doing something wrong here? Do I have problems with the flow after didChangeAuthorizationStatus gets called?
From other user reports, it seems that kCLErrorDomain 5 is a 'catch all' for region monitoring fails; it doesn't provide much useful information. I believe that your issue is being caused by the line
[locationManager requestStateForRegion:region]; // check if already inside region
which you're calling from inside the delegate method didStartMonitoringForRegion:
I saw something very similar in my own project and taking this line out (or delaying its execution for a while) solved the issue. My best guess is that iOS is still doing running some internal region monitoring code when this delegate method fires, so it's not an appropriate time to call requestStateForRegion:
Try taking this out and see if it is the answer.
kCLErrorDomain code/error 5 means that you have tried to monitor more than 20 CLRegions.
Descriptio here
see startMonitoringForRegion description It says:
An app can register up to 20 regions at a time. In order to report region changes in a timely manner, the region monitoring service requires network connectivity.
kCLErrorDomain 5 is a catch all that can mean many different things.
One of the sources is when you call [locationManager requestStateForRegion:region] which is necessary when you first monitor for a region to know if you're already in the region or not. This is because the didEnter region will only be called when you actually enter the region. Usually this means the first time you monitor for the region, you must wait 5 seconds until the region is not detected, and only then will didEnter region fire off the next time you're in the region.
There are many different reports of causes to the problem:
Ensure no more than 20 beacons are being monitored
5 means "regionMonitoringFailure". Ensure the radius is not too large (not relevant for beacon monitoring).
Ensure location updates are registered
Omit calling requestStateForRegion, however I described above why it's necessary to do so.
Restarting device and bluetooth may help
Try with 30 second delay
None of these worked for me, however. I think my root cause was similar to the iOS 7.1 bug where it just randomly stopped working on some devices. I tried the restart and restart of bluetooth, nothing helped.
Not sure what changed, but I just tried again the next day and it started working.
Basically you may want to try a different device until this one starts working again.
I am trying to use location monitoring in my app. I can set my location and reverseGeocode the location I want to monitor. the didUpdateToLocation delegate method works fine, and updates continuously but the didStartMonitoingForRegion delegate never gets called, nor do the didExitRegion nor didEnterRegion.
Any suggestions?
- (IBAction)setLocation:(UIButton *)sender {
if(!self.locationManager) self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:10]; // Update again when a user moves distance in meters
[self.locationManager setPurpose:#"Set location based alerts if switch is on"];
self.plugLocation=nil; //reset to nil so didUpdateToLocation will update it
self.distanceLabel.text=[NSString stringWithFormat:#"%d",0];
[self.locationManager startUpdatingLocation];
if ( ![CLLocationManager regionMonitoringAvailable] || ![CLLocationManager regionMonitoringEnabled] ){
NSLog(#"Location monitoring not Unavailable");
}else {
}
}
-(void)setPlugLocation:(CLLocation *)plugLocation{
//
if (!_plugLocation) _plugLocation=[[CLLocation alloc]init];
_plugLocation=plugLocation;
if (_plugLocation) {
[self setRegion:plugLocation radius:20 name:self.plugName];
[self reverseGeocode:self.plugLocation];
NSLog(#"setPlugLocation %#", [self.plugLocation description]);
}
}
-(void)setRegion:(CLLocation *)center radius:(double)meters name:(NSString*)name{
CLLocationCoordinate2D plug2D;
plug2D.latitude=center.coordinate.latitude;
plug2D.longitude=center.coordinate.longitude;
CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:plug2D radius:meters identifier:name];
[self.locationManager startMonitoringForRegion:region desiredAccuracy:kCLLocationAccuracyBest];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
self.latitudeLabel.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.latitude];
self.longitudeLabel.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.longitude];
if (self.plugLocation == nil)self.plugLocation = newLocation;
if (self.plugLocation!=nil) {
CLLocationDistance distanceBetween = [newLocation distanceFromLocation:self.plugLocation];
NSLog(#"didUpdateToLocation Distance from plug=%f",distanceBetween);
self.distanceLabel.text=[NSString stringWithFormat:#"%f",distanceBetween];
}
}
-(void)reverseGeocode:(CLLocation *)coordinates;{
if (!self.plugGeo) self.plugGeo = [[CLGeocoder alloc] init];
[self.plugGeo reverseGeocodeLocation:coordinates completionHandler:^(NSArray *placemarks, NSError *error) {
if (error==nil&&[placemarks count]>0) {
CLPlacemark *placemark=[placemarks objectAtIndex:0];
NSLog(#" setPlugLocation geocodeAddressString %#",placemark);
//should also transfer back to plug detail and save
self.locationLabel.text=[NSString stringWithFormat:#"%# %#\n%#, %#", placemark.subThoroughfare, placemark.thoroughfare, placemark.locality,placemark.postalCode];
[self sendAlertMessage:[NSString stringWithFormat:#"%# %#\n%#, %#", placemark.subThoroughfare, placemark.thoroughfare, placemark.locality,placemark.postalCode] title:#"Success"];
}else {
NSLog(#" setPlugLocation couldn't geoCode address %#",error);
}
}];
}
Are you using the simulator to test your application? Something that I've found is that the simulator is completely unreliable for region exit/enters. Try compiling the project on your device by plugging it in and changing from iPhone Simulator to your iOS device. You can then unplug your device and run your app from your phone to test it.
Why doesn't the simulator work for regions? Regions are mostly determined by Apple's hidden algorithm using Wi-Fi, cell towers, and other applications on the phone requesting location. Seeing as a simulator doesn't use Wi-Fi or cell towers... region monitoring is going to be pretty impossible.
It's likely your code is fine (I see no glaring errors), but the simulator is giving you bad results. Try it on your device and let us know if it does the same thing.