The following code results in null coordinates. The weird thing is the UIAlert prompting the app to use current location appears briefly before the user can select yes.
My code which i have used :
CLLocationManager *locationManager;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
float latitude = locationManager.location.coordinate.latitude;
float longitude = locationManager.location.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
The NSLog prints 0.0000000 for both coordinates.
Thanks!
The reason you're getting 0 is because the location manager hasn't collected any data at that point (it has started thought)
You need to set your class as the delegate of the location manager (ie supplying a function that is called whenever a new location is retrieved), and also retain your location manager.
// Inside .m file
#interface MyClass () <CLLocationManagerDelegate> // Declare this class to implement protocol CLLocationManagerDelegate
#property (strong, nonatomic) CLLocationManager* locationManager; // Retains it with strong keyword
#end
#implementation MyClass
// Inside some method
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
// Delegate method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation* loc = [locations lastObject]; // locations is guaranteed to have at least one object
float latitude = loc.coordinate.latitude;
float longitude = loc.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
}
Related
I have searched a lot and didn't get any satisfactory answer, I have a scenario where I am showing a list of sellers based on user's current location. I am getting a location for the first time and when I run my App afterward whenever I try to get the location I am getting a cache location data. I did try after some time even after every 24 hours but still getting the cache location where my current location is changed as well. Following is the code I am using for reference. please advise.
Property defined in Header file
#property (nonatomic,retain) CLLocationManager *locationManager;
- (void)startSingleLocationRequest
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[self.locationManager startUpdatingLocation];
[self.locationManager requestWhenInUseAuthorization];
}
#pragma mark --didUpdateLocations
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
self.latitudeValue = locations.lastObject.coordinate.latitude;
self.longitudeValue = locations.lastObject.coordinate.longitude;
// location set for simulation to UK
if(self.latitudeValue != 51.509979 && self.longitudeValue != -0.133700){
[MBProgressHUD hideHUDForView:self.outletSearchNearBy animated:YES];
[self.locationManager stopUpdatingLocation];
abc *slv =[self.storyboard instantiateViewControllerWithIdentifier:#"abc"];
slv.receivedLatitudeValue = self.latitudeValue;
slv.receivedLongitudeValue = self.longitudeValue;
[self.navigationController pushViewController:slv animated:YES];
}
else{}
}
You can do something like,
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
for(int i=0;i<locations.count;i++){
CLLocation * newLocation = [locations objectAtIndex:i];
CLLocationCoordinate2D theLocation = newLocation.coordinate;
CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 5.0)
{
continue;
}
// do your all stuff here and then
break;
}
}
Your code will not executes if your location age is more than 5 seconds. You can decide location age lie 10 seconds or 20 seconds!
Update :
Just replace your property declaration
#property (nonatomic,retain) CLLocationManager *locationManager;
with
#property (nonatomic,strong) CLLocationManager *locationManager;
or
just declare it as instance variable like,
CLLocationManager *locationManager;
and remove self from avery instance of it!
Second thing,
You should do first,
[self.locationManager requestWhenInUseAuthorization];
and then start update of location,
[self.locationManager startUpdatingLocation];
Can you try like this
self.locationManager.pausesLocationUpdatesAutomatically = NO;
Because it
Specifies that location updates may automatically be paused when possible.
By default, this is YES for applications linked against iOS 6.0 or later.
On the other hand, kCLLocationAccuracyBestForNavigation uses top speed GPS. So better to use this instead of kCLLocationAccuracyNearestTenMeters.
Lion thanks for the support, actually i was checking location inside the plaza and due to that i was not getting the right location, i tested by coming outside and it is showing perfectly. anyways thanks lion you have been really helpful.
I need to pick coordinates of current marker position on Google maps. It should update coordinates as marker is moving on map.
I'm using GoogleMaps , GooglePlaces and GooglePlacePicker API's. I can get nearby places using GooglePlacePicker API but I want to pick exact coordinates of location where marker is present.
It is already done in Uber?
Use this,
.h
#interface ViewController : UIViewController <CLLocationManagerDelegate> {
GMSMapView *mapView_;
GMSMarker *marker_;
float currentLatitude;
float currentLongitude;
}
#property(nonatomic,retain) CLLocationManager *locationManager;
#property (nonatomic)CLLocationCoordinate2D coordinate;
.m
- (void)viewDidLoad {
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
[_locationManager setDelegate:self];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if (IS_OS_8_OR_LATER) {
if ([_locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[_locationManager requestWhenInUseAuthorization];
}
}
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
NSLog(#"%#",locations);
CLLocation *currentLoc=[locations objectAtIndex:0];
NSLog(#"CurrentLoc : %#",currentLoc);
_coordinate=currentLoc.coordinate;
currentLatitude = currentLoc.coordinate.latitude;
currentLongitude = currentLoc.coordinate.longitude;
}
-(void)plotMarkerForLatitude:(float)latitude andLongitude:(float)longitude {
// Now create maker on current location
if (marker_ == NULL) {
marker_ = [[GMSMarker alloc] init];
}
CLLocationCoordinate2D target =
CLLocationCoordinate2DMake(latitude, longitude);
marker_.position = target;
marker_.title = #"title";
marker_.appearAnimation = kGMSMarkerAnimationPop;
NSLog(#"%f %f",latitude,longitude);
marker_.icon = [UIImage imageNamed:#"marker"];
marker_.snippet = #"Address";
marker_.map = mapView_;
}
In Plist :
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow access to get your current location</string>
This can possibly be done by implementing the GMSMapViewDelegate protocol. See the guide to events and the list of methods on the GMSMapViewDelegate.
As mentioned in the documentation,
Applications can use this event to trigger a refresh of markers or other content being displayed on the GMSMapView, rather than, for example, reloading the content on every camera change.
You may also check Google Maps SDK for iOS for more information on what other APIs you can use along with Maps iOS SDK to build location-relevant apps and sites.
Using iOS 8 and have NSLocationAlwaysUsageDescription set.
Here is my code:
#import "GeoLocation.h"
#import "AppDelegate.h"
#implementation GeoLocation
- (id)init
{
self = [super init];
if (self)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 5; //in meters
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
self.numberOfUpdates = 0;
[self.locationManager startUpdatingLocation];
}
return self;
}
// Wait for location callbacks
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"Location Updated: %#", [locations lastObject]);
}
- (float) getLatitude
{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSLog(#"getLatitude: %f", self.locationManager.location.coordinate.latitude);
appDelegate.gMyProfile.latitude = self.locationManager.location.coordinate.latitude;
return self.locationManager.location.coordinate.latitude;
}
- (float) getLongitude
{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSLog(#"getLongitude: %f", self.locationManager.location.coordinate.longitude);
appDelegate.gMyProfile.longitude = self.locationManager.location.coordinate.longitude;
return self.locationManager.location.coordinate.longitude;
}
- (float) getAltitude
{
return self.locationManager.location.altitude;
}
When the user logs in, I instantiate a GeoLocation object, which turn on starts updating the location.
If I use
self.locationManager.distanceFilter = 5;
and walk around my house, didUpdateLocations won't fire.
However, if I get rid of
self.locationManager.distanceFilter = 5;
didUpdateLocations will fire every second.
Anything you guys see that I am not. I would love for this to update when the user moves 5 meters.
Adding a distance filter will most likely cause iOS to take the horizontalAccuracy into account.
Since you are inside you will be unlikely to get location with a horizontalAccuracy of 5 which is the best accuracy.
Without the distance filter you are probably just getting the same location or another location within the distance in horizontalAccuracy.
Generally you will only get an accuracy of 5m meters when you are outside in clear view of the satellites above you and not next to tall buildings that can reflect and obscure the signal.
I'm wondering if it's problematic to implement two different SDK's that use CLLocationManager functionality in one app.
Both SDK's are monitoring CLBeaconRegions, and both have implemented different classes with CLLocationManager instances and delegate implementations.
Possible problems:
What if one of the SDK's removes all monitored CLBeaconRegions from it's CLLocationManager. Does that influence the other SDK's CLLocationManager as well?
What if both SDK's start looking for the same UUID (but with a different CLBeaconRegion identifier)... do both get a delegate call?
I can't think of any other reason why this shouldn't work, but maybe I'm missing something?
Have you tried with Shared Instance ?
What you can do is try to manage your code with same location manager instance.
So any change in delegate may reflect in single class from there you can manage you code .
Example :-
.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationManager : NSObject <CLLocationManagerDelegate>
#property (nonatomic,strong) CLLocationManager *objLocationManager;
#property (nonatomic,assign) CLLocationCoordinate2D currentcoordinate;
+ (LocationManager *) SharedInstance;
+ (CLLocation *) currentLocation;
#end
.m
#define currentCordinates [LocationManager SharedInstance].currentcoordinate
#define currentLocationmanger [LocationManager SharedInstance].objLocationManager
// Shared Manager
static LocationManager *SharedInstance = nil;
+ (LocationManager *) SharedInstance
{
#synchronized(self)
{
if (SharedInstance == nil)
{
SharedInstance = [[super allocWithZone:NULL] init];
currentLocationmanger = [[CLLocationManager alloc]init];
currentLocationmanger.delegate = [LocationManager SharedInstance];
/* Pinpoint our location with the following accuracy:
*
* kCLLocationAccuracyBestForNavigation highest + sensor data
* kCLLocationAccuracyBest highest
* kCLLocationAccuracyNearestTenMeters 10 meters
* kCLLocationAccuracyHundredMeters 100 meters
* kCLLocationAccuracyKilometer 1000 meters
* kCLLocationAccuracyThreeKilometers 3000 meters
*/
currentLocationmanger.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
/* Notify changes when device has moved x meters.
* Default value is kCLDistanceFilterNone: all movements are reported.
*/
currentLocationmanger.distanceFilter = 2.0f;
/* Notify heading changes when heading is > 5.
* Default value is kCLHeadingFilterNone: all movements are reported.
*/
currentLocationmanger.headingFilter = 5;
[LocationManager SharedInstance].geocoder = [[CLGeocoder alloc] init];
[[LocationManager SharedInstance].objLocationManager startUpdatingLocation];
// update location
if ([CLLocationManager locationServicesEnabled]){
[currentLocationmanger startMonitoringSignificantLocationChanges];
}
}
}
return SharedInstance;
}
//other delgates and stuff to manage in .m
Some where in when you use is use with shared intace
//region.span = span;
region.center = [LocationManager SharedInstance].currentcoordinate;
I have IBAction:
-(IBAction)pressStart{
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
In
- (void)viewDidLoad
{
[super viewDidLoad];
duration.text = #"00:00:00";
speedLabel.text = #"00";
locationManager = [[CLLocationManager alloc]init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
And this method:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
CLLocation *firstLocation = [locations objectAtIndex:0];
location = [locations lastObject];
CLLocationDistance meters = [location distanceFromLocation:firstLocation];
NSLog(#"meters= %f", meters);
And I don't know why the firstLocation is changing. Maybe there is a way to capture firstLocation? This should be the location of the device when the button Start is pressed.
firstLocation in your code is not the first location since location updates started; it is the first location to be returned to you since the previous callback to the locationManager:didUpdateLocations: method (the location services may collect multiple locations before calling back to your delegate method in certain circumstances -- the most recent location is always going to be the last object in the locations array).
If you need to store the first location since location updates started, you should create a property such as
#property (nonatomic, strong) CLLocation *startingLocation;
Then in the locationManager:didUpdateLocations: method, add the code:
if (!self.startingLocation) {
self.startingLocation = [locations objectAtIndex:0];
}
That will store the starting location into the property after the first callback. (You can set the property to nil if you want to reset it.)
Don't forget that the very first location you receive many not be very accurate, as it takes time for location services to get a fix on the device's position if they were not recently enabled.