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.
Related
I'm using Parse and with geoPointForCurrentLocationInBackground I can stop updating once a location is received without having to manually stop it.
How do I stop updating location immediately right after I receive location using CLLocationManager?
Edit
I know [self.locationManager stopUpdatingLocation]; stops it.
What I'm really asking is, how do I know I've received location for the first time then stop it immediately?
After getting your location, use this method:
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
Call stopUpdatingLocation as soon as your didUpdateLocations method is called.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[manager stopUpdatingLocation];
//store your location
self.location = [locations lastObject];
}
BOOL first_time = YES; // public
Every time you start updating location set first_time to YES:
first_time = YES;
[self.locationManager startUpdatingLocation];
in your didUpdateUserLocation method:
if (userLocation == nil) {
NSLog(#"User location is nil. maybe wating for permission");
} else if (!CLLocationCoordinate2DIsValid(userLocation.coordinate)) {
NSLog(#"User location is not valid 2d coordinates. maybe called in background");
} else {
NSLog(#"Did update user location: %f %f", userLocation.location.coordinate.latitude, userLocation.location.coordinate.longitude);
// here is the first time you receive user location
if (first_time)
{
first_time = NO;
[self.locationManager stopUpdatingLocation];
}
}
call below method to save and stop location after you get it once
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
self.location = [locations lastObject]
self.locationManager.delegate = nil;
[self.locationManager stopUpdatingLocation];
}
The opposite of stopMonitoringSignificantLocationChanges is not stopUpdatingLocation, it is startMonitoringSignificantLocationChanges.
Check out the CLLocation documentation for further detail.
Finally found the answer in another question...reprinting it here because it took me a while to stumble on it.
I had to call this:
[_locationManager stopMonitoringSignificantLocationChanges];
Even though I never called startMonitoringSignificantLocationChanges in the first place, seems I had to "un-call" it...strange that it works this way, but as soon as I added that line, location services shut down promptly. Hope this helps someone else.
Once current location update stop location manager using stopUpdatingLocation.
region.center = self.mapView.userLocation.coordinate;
if (region.center.longitude != 0 && region.center.latitude != 0) {
[self.locationManager stopUpdatingLocation];
}
self.yourLocationManager.stopUpdatingLocation()
I was asked to code a small app for iOS in Objective C that's supposed to choose the closest object of a user, in a set of coordinates
The plan was to load the coordinates of the user only once, when the application loads for the first time.
Here's my current code :
(void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.headingFilter = 1;
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
self.userLat = self.locationManager.location.coordinate.latitude;
self.userLon = self.locationManager.location.coordinate.longitude;
NSLog(#" ----------------------------- ");
NSLog(#"User lat : %lf", self.userLat);
NSLog(#"User lon : %lf", self.userLon);
NSLog(#" ----------------------------- ");
}
I don't have a Apple iOS developper program, so I'm stuck with the iOS simulator from xCode.
I try to set some custom coordinates in the iOS simulator through debug, like this :
When i execute the app (obviously after setting coordinates), the log has userLat and userLon to 0.00..
Apr 6 03:16:20 Locals-Mac.local app[5683]: -----------------------------
Apr 6 03:16:20 Locals-Mac.local app[5683]: User lat : 0.000000
Apr 6 03:16:20 Locals-Mac.local app[5683]: User lon : 0.000000
Apr 6 03:16:20 Locals-Mac.local app[5683]: -----------------------------
I remember hearing somewhere that the iOS simulator don't work with the CoreLocation library (It might be right or wrong, i wouldn't know).
Is it the reason the lat/lon values are 0?
If the reason is indeed the iOS simulator, does this code give user current location?
Thanks in advance!
Edit :
With the answer and comments, i'm now using the didUpdateLocations callback function :
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
self.userLat = location.coordinate.latitude;
self.userLon = location.coordinate.longitude;
NSLog(#" ----------------------------- ");
NSLog(#"User lat : %lf", self.userLat);
NSLog(#"User lon : %lf", self.userLon);
NSLog(#" ----------------------------- ");
}
I ask xCode to simulate my position to London with the Scheme option that follows :
My new load function :
-(void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.headingFilter = 1;
self.locationManager.delegate = self;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[self.locationManager requestWhenInUseAuthorization];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
}
This code still doesn't print the NSLog that was put in the location callback function. Did i miss something?
The location manager doesn't instantly have the user's location when you start updating it. If you check the location property right after calling startUpdatingLocation it is usually going to be nil unless some other app was recently updating it. You need to implement the locationManager:didUpdateLocations: delegate method which will be called once it has a location.
You also need to check and possibly request for location permissions.
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
I am writing both Android and iOS apps which need to find BLE beacons around the device.
When I run my code from Android, it finds several beacons in the room I am in.
I have 8 beacons.
When I run the beacon code from iPhone, it returns a list of exactly 0 beacons.
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self initRegion];
[self locationManager:self.locationManager didStartMonitoringForRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
- (void)initRegion {
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:BEACONUUID];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:BEACONIDENTIFIER];
[self.locationManager startMonitoringForRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(#"Beacon Found");
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"Left Region");
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
self.beaconFoundLabel.text = #"No";
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
CLBeacon *beacon = [beacons lastObject];//<== is always 0
self.beaconFoundLabel.text = #"Yes";
self.proximityUUIDLabel.text = beacon.proximityUUID.UUIDString;
self.majorLabel.text = [NSString stringWithFormat:#"%#", beacon.major];
self.minorLabel.text = [NSString stringWithFormat:#"%#", beacon.minor];
self.accuracyLabel.text = [NSString stringWithFormat:#"%f", beacon.accuracy];
if (beacon.proximity == CLProximityUnknown) {
self.distanceLabel.text = #"Unknown Proximity";
} else if (beacon.proximity == CLProximityImmediate) {
self.distanceLabel.text = #"Immediate";
} else if (beacon.proximity == CLProximityNear) {
self.distanceLabel.text = #"Near";
} else if (beacon.proximity == CLProximityFar) {
self.distanceLabel.text = #"Far";
}
self.rssiLabel.text = [NSString stringWithFormat:#"%ld", (long)beacon.rssi];
}
In my didRangeBeaconsInRegion, the beacons NSArray always comes up with 0 objects.
Though I have 8 objects. And i've downloaded several apps that are not mine, and they all see several of my beacons.
Why doesn't my code see any of my beacons?
Here is what I do whenever I'm setting up an iBeacon app.
Not all these things are necessary, but it will
work
keep your user happy
(maybe most importantly) keep Apple happy
iOS 8+ Only
First things first: if you're using iOS 8, you need to make sure you actually have access before using CLLocationManager.
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
// You can either use requestAlwaysAuthorization, or requestWhenInUseAuthorization
[self.locationManager requestAlwaysAuthorization];
You'll also need an entry for NSLocationAlwaysUsageDescription in your plist (again, iOS 8 only )
iOS 7+
Your App's pList
Regardless you're using iOS 8 or 7, you should add the following to your plist file (you need to decide if you'll use background or not).
Note: The below is in the form of KEY : KEY TYPE : VALUE for string, and KEY : KEY TYPE : [ Value1, Value2... ] for Arrays:
NSLocationUsageDescription : String : "Gimmie access to your location or else..."
NSBluetoothPeripheralUsageDescription : String : "Gimmie access to your blue tooth or else"
// Optionally supply if you need background modes. I don't believe you need this either if you plan to turn these options on using the Capabilities section of your App's Settings (see below section)
UIBackgroundModes : Array : [ location, bluetooth-central ]
UIApplicationExitsOnSuspend : Boolean : NO
Your App's Project Settings (Capabilities)
this section has been removed as this can cause your app to be rejected (as noted by #heypiotr in the comments)
Final Thoughts
A final suggestion would be to try moving [self locationManager:self.locationManager didStartMonitoringForRegion:self.beaconRegion] into your viewDidAppear.
Here is an example of what I typically do ( which works quite well for me ).
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self initLocationManager];
[self initBeaconRegion];
[self startMonitoring];
}
-(void)initLocationManager {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Not necessary, but I like to do it.
if( ![CLLocationManager locationServicesEnabled] ) {
[self.locationManager startUpdatingLocation];
}
// Only necessary if you're in iOS 8. Checking for existence though to support iOS 7
if( ![CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized ) {
if ([CLLocationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager performSelector:#selector( requestAlwaysAuthorization )];
}
}
}
-(void)initBeaconRegion {
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:kYOUR_UUID_HERE];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:kYOUR_IDENTIFIER_HERE];
// Change this to whatever you want....
self.beaconRegion.notifyEntryStateOnDisplay = YES;
self.beaconRegion.notifyOnEntry = NO;
self.beaconRegion.notifyOnExit = YES;
}
# pragma mark -
# pragma mark Monitoring Beacons
# pragma mark -
-(void)startMonitoring {
// Monitor Beacon signals around me and report them back to me
[self.locationManager startMonitoringForRegion:self.beaconRegion];
}
The last part ( placement in viewDidAppear ) may or may not help - it all depends I guess on too many factors to consider in a stackoverflow response.
Hope that helps and good luck!
Final Edit
Forgot one more thing that may help. There are some helpful methods that you can implement that can help you debug the issue further. Here is an example of a few of them:
#pragma mark Authorization Status Changed
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if( ![CLLocationManager locationServicesEnabled] ) {
NSLog(#"Couldn't turn on ranging: Location services are not enabled.");
} else {
NSLog(#"Location services ARE enabled.");
}
if( [CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized ) {
NSLog(#"Couldn't turn on monitoring: Location services not authorized.");
} else {
NSLog(#"Location services ARE authorized.");
}
}
#pragma mark -
#pragma mark CLLocationManager Errors
#pragma mark -
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog( #"FAIL ERROR: %#", [error description] );
}
-(void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion (CLBeaconRegion *)region withError:(NSError *)error {
NSLog( #"RANGE BEACONS ERROR: %#", [error description] );
}
First check with the other app like.Locate app add your UDID and check this app is showing your iBeacon. if not then there is a problem with apple IOS sometimes. then remove the app. Restart the app. it will work for you.
We had similar problem before, make sure your iBeacon device respond the scan request from iOS with a response DOES not contain manufacturer specific field.
Please check this note from apple
Before attempting to monitor any regions, your app should check whether region monitoring is supported on the current device. Here are some reasons why region monitoring might not be available:
The device doesn’t have the necessary hardware to support region
monitoring.
The user denied the app the authorization to use region monitoring.
The user disabled location services in the Settings app.
The user disabled Background App Refresh in the Settings app, either for the device or for your app.
5.The device is in Airplane mode and can’t power up the necessary hardware.
In iOS 7.0 and later, always call the isMonitoringAvailableForClass: and authorizationStatus class methods of CLLocationManager before attempting to monitor regions. (In OS X v10.8 and later and in previous versions of iOS, use the regionMonitoringAvailable class instead.) The isMonitoringAvailableForClass: method tells you whether the underlying hardware supports region monitoring for the specified class at all. If that method returns NO, your app can’t use region monitoring on the device. If it returns YES, call the authorizationStatus method to determine whether the app is currently authorized to use location services. If the authorization status is kCLAuthorizationStatusAuthorized, your app can receive boundary crossing notifications for any regions it registered. If the authorization status is set to any other value, the app doesn’t receive those notifications.
Apple link goes here
I have an app which uses the device location. If they allow the location, I want to run my method getDataFromJson and run my app as normal. If they deny it, or have denied it before, I wish to show them a view explaining they need to go to settings and allow it.
I have a lot of code, but it doesn't work at the moment. Can anyone help explain where the problem is?
Many thanks!
- (void)viewDidLoad
{
[super viewDidLoad];
if ([CLLocationManager authorizationStatus] == YES) {
//are enabled, run the JSON request
[self getDataFromJson];
} else {
//is not enabled, so set it up
NSLog(#"no");
[locationManager location];
};
}
-(CLLocationCoordinate2D) getLocation{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
return coordinate;
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusDenied) {
//location denied, handle accordingly
locationFailView.hidden = NO;
mainView.hidden = YES;
}
else if (status == kCLAuthorizationStatusAuthorized) {
//hooray! begin tracking
[self getDataFromJson];
}
}
//class to convert JSON to NSData
- (IBAction)getDataFromJson {
CLLocationCoordinate2D coordinate = [self getLocation];
NSString *latitude = [NSString stringWithFormat:#"%f", coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:#"%f", coordinate.longitude];
...
}
+ (CLAuthorizationStatus)authorizationStatus
Return Value A value indicating whether the application is authorized
to use location services.
Discussion The authorization status of a given application is managed
by the system and determined by several factors. Applications must be
explicitly authorized to use location services by the user and
location services must themselves currently be enabled for the system.
This authorization takes place automatically when your application
first attempts to use location services.
+ (BOOL)locationServicesEnabled
Returns a Boolean value indicating whether location services are
enabled on the device.
You may check this two state: locationServicesEnabled and authorizationStatus then decide which method should use.
AuthorizationStatus should check with states:
typedef enum {
kCLAuthorizationStatusNotDetermined = 0,
kCLAuthorizationStatusRestricted,
kCLAuthorizationStatusDenied,
kCLAuthorizationStatusAuthorized
} CLAuthorizationStatus;
but you check equal with bool value in viewDidLoad method.