Why are location services not being used after I allow them? - ios

In my iOS application, I have a table that uses your location to find data that is near you. I just installed it on my iPhone today, and when location services were needed, I got the expected alert that said "MyAppName would like to use your current location" and once I pressed OK, the app basically froze. When I closed the app and reopened it however, it worked perfectly fine. Now that I think about it, this happened on the simulator as well, as I have to run the app a couple times before location services works properly there too. Has this happened to anyone else, and do you know how to fix this? I don't want my users to have to close the app and reopen it for location services to work properly.
Here is some relevant code:
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"%#",error.userInfo);
if([CLLocationManager locationServicesEnabled]){
NSLog(#"Location Services Enabled");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Need Your Location"
message:#"Please go to Settings and turn on Location Services so you can see who's near you."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
_thisGeoPoint = [PFGeoPoint geoPointWithLatitude:currentLocation.coordinate.latitude
longitude:currentLocation.coordinate.longitude];
}
[locationManager stopUpdatingLocation];
located = true;
}

This is happening because locationManager stops running when it doesn't initially have permission. So you will need to re-run it once you detect that the permission has changed. You can check if the permission changed using the didChangeAuthorizationStatus delegate method.
So something like this:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
if (status == kCLAuthorizationStatusAuthorized) {
[locationManager startUpdatingLocation];
}
}

Related

iOS 8 CLLocationManager

I am trying to just NSLog co-ordinates in my console, but it is not working.
I have the core location linked in header
#implementation ViewController {
CLLocationManager *locationManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSLog(#"%f", currentLocation.coordinate.longitude);
NSLog(#"%f", currentLocation.coordinate.latitude);
}
}
But I am not getting anything in the console, does anybody know what could be going wrong?
Since iOS 8 you have to ask for user's permission before starting to update the location.
Before that you have to add the messages that the user will receive alongside the request for permission. In your .plist file add those 2 keys (if you want to use both types of location fetching) and fill them with your own message: NSLocationWhenInUseUsageDescription ,NSLocationAlwaysUsageDescription
Afterwards ask for permission, right before starting the CLLocationManager:
[self.locationManager requestWhenInUseAuthorization];
or / and
[self.locationManager requestAlwaysAuthorization];
To avoid crashes on iOS 7 and below you can define a macro to check the OS version:
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
And then you can do:
if(IS_OS_8_OR_LATER) {
// Use one or the other, not both. Depending on what you put in info.plist
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
Now it should work.
Macro source: iOS 8 Map Kit Obj-C Cannot Get Users Location

iOS: Get Coordinates on button click, then stop all location services

Right now, I have it so when a button is clicked, it starts location services, sets the latitude/longitude variables. But location still continues to be running in the background.
I want is so when I click a button it finds the latitude/longitude, all location services stop.
Here's what I have currently.
- (IBAction)startButton:(id)sender {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
NSLog(#"%#", [self lat]);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
[self setLat:[NSString stringWithFormat:#"%.6f", currentLocation.coordinate.latitude]];
}
}
Another problem is, if I instantly try to retrieve the value of the lat property, it returns null, most likely because it takes a second or two to find the location.
So I would also need to stop any further code to be run until the lat/long properties are set. For example, How would I stop the otherFunction from running until the latitude/longitude are found:
- (IBAction)startButton:(id)sender {
[self updateLocation];
[self otherFunction];
}
- (void)updateLocation
{
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
[self setLat:[NSString stringWithFormat:#"%.6f", currentLocation.coordinate.latitude]];
[locationManager stopUpdatingLocation]
}
}
Any help/ideas would be appreciated!
In your last function, after you verify that the currentLocation is not nil, then you should check for the accuracy of currentLocation, then call your setLat: function, then stop updating the location. See this post for more details:
CLLocationManager and accuracy issues - any experiences?

How to get 'current location only' in iOS?

I am using Core Location framework to getting location in iOS. I use, CLLocationManager *locationManager; and call [locationManager startUpdatingLocation];
Problem is I only need instantaneous location but startUpdatingLocation keep on giving me location. To stop this I can use [self.locationManager stopUpdatingLocation], but this look like a way out or hack.
Is there any better way to just get current location in iOS?
in your .h file
#import <CoreLocation/CoreLocation.h>
#interface LocationSearchViewController : UIViewController<UITextFieldDelegate,CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
in your .m file
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
[locationManager stopUpdatingLocation]; // when u got the lat and long it stop uoatde the location
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSString *getcurrlong = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
NSSting *getcurrlat = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}
You can't think of location in those precise terms. You'll get back increasingly accurate locations from the location manager and it's up to you to decide when it's accurate enough. You have to weigh this against power usage and time. The location updates will never be completely accurate. The will never be returned immediately. The device has to power up hardware, then listen for GPS/WiFi/Cell signals and use all those to calculate location.
There's no way to ask for "my precise current location" and have it given to you immediately. Location is not a property like [NSDate date]. You can only ask for best-estimate location updates and they will only come to you in imprecise measurements, and never instantaneously (excepting cached location).
Check it
-(void)getCurrentLocation
{
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
startLocation = nil;
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (startLocation == nil)
{
startLocation = newLocation;
[locationManager setDelegate:nil];
locationManager = nil;
}
}

CLLocationManager delegate not called in my project using Typhoon framework

I am using typhoon framework in my application. My application working fine. Now I want to location updates in my app. I added the Location framework and implemented the code.
But my CLLocationManger delegates method is not working.
I copied the same code in demo app witch do not have any dependency and the same code start working and I am able to get the location updates.
Does anyone can tell me what can be the possible reason of such behavior.
Here is the code that I am using:
In my LoginViewController.m i am using following code in - (void)viewDidLoad method
if (![CLLocationManager locationServicesEnabled]) {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Location Services Disabled", nil)
message:NSLocalizedString(#"You currently have all location services for this device disabled. If you proceed, you will be asked to confirm whether location services should be reenabled.", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK", nil)
otherButtonTitles:nil] show];
} else {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
}
This does not sound related to Typhoon. We're not aware of anything in the framework that would prevent CLLocationManager from working correctly. Also, there are many published apps in the store that are using location services. In fact, the very first Typhoon application used location services.
A common problem with location manager is forgetting to tell it to start sending updates. Be sure to do the following:
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[_locationManager startUpdatingLocation]; //This is required!
[_locationManager startUpdatingHeading]; //This is required!
If you wished you could also build a location manager in Typhoon, and inject it, as long as the above to steps to start updating are called.
Not sure about Typhoon, but make sure you're keeping a strong reference to the manager to keep it throughout the life time of your class, and of course to correctly assign its delegate.

How to make my ios app appears in Location Services in the settings

I wrote an CLLocationManager ios app. However, I cannot see my app appears in the Location Services in the settings on my iPhone. Do I need to set a specific value in plist in my ios project in Xcode? Thanks in advance!
It should appear automatically once code that actually requires location tracking is being called (whenever the popup first show: do you allow...)
try calling something like this:
[self.locationManager startUpdatingLocation];
And that should do it
In iOS -8 need to do some changes :
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]){
[locationManager requestWhenInUseAuthorization];
}else{
[locationManager startUpdatingLocation];
}
need to add 2 extra key in plist with blank value
1)NSLocationWhenInUseUsageDescription
2)NSLocationAlwaysUsageDescription
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSString *strLat = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
NSString *strLong = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}

Resources