Getting coordinates CLLocationManager IOS - ios

I'm trying to getting my current location exact according to my coordinates. I've implemented CLLocationManager in my viewController called myLocation.
My problem is, I'm getting not getting my co-ordinates for the first time, but when I again approach I got the coordinates. I'm unable to understand this problem that why this not appear for the first time.
I also tried to give a NSTimer to stoplocation but but still unable to get the result for the first time, every first time I getting a (null) value, and then getting the co-ordinates.
My Code:
#import <UIKit/UIKit.h>
#import <Corelocation/CoreLocation.h>
#interface myLocation : UITableViewController<CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#interface myLocation () {
CLLocationManager* _locationManager;
NSString * _lat;
NSString * _lng;
}
#end
#implementation myLocation
- (void)viewDidLoad
{
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[_locationManager requestWhenInUseAuthorization];
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
[_locationManager stopUpdatingLocation];
_lat =[NSString stringWithFormat:#"%f",location.coordinate.latitude];
_lng =[NSString stringWithFormat:#"%f",location.coordinate.longitude];
}
- (void)viewWillAppear:(BOOL) animated
{
NSLOG(#"%#",_lat);
NSLOG(#"%#",_lng);
}

Your coordinates aren't appearing yet when you attempt to print them in viewWillAppear: because the CLLocationManager hasn't had enough time to retrieve the first location yet. Wait until didUpdateLocations: is first called before attempting to utilize the device coordinates because didUpdateLocations: is where you'll be receiving those coordinates. I recommend deleting your attempt to print the coordinates code from your viewWillAppear and simply print them in didUpdateLocations: instead.
In the comments, the OP stated he wants to "refresh" the location during viewWillAppear. I suggest stopping the updates when the view disappears and restarting the updates as soon as the view reappears:
- (void)viewWillAppear:(BOOL) animated
{
[_locationManager startUpdatingLocation];
}
- (void)viewWillDisappear:(BOOL) animated
{
[_locationManager stopUpdatingLocation];
}

It takes some time for location services to start up and call your delegate method - This almost certainly won't happen before viewWillAppear is called if you are only starting location services in viewDidLoad. Also, the first time your app executes it has to wait for the user to grant permission.
You can examine the location property of your CLLocationManager to get the most recent location. If it is nil then no location has been determined (yet).

Related

Getting Current Location instead of Cache ios

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.

Retrieving location on the Apple Watch

I want to get the latitude and longitude of the user and display it on the Apple Watch.
I have already included the core location framework in my Watchkit Extension.
When I run the program all I get for the lat and long is 0.0 and 0.0
I tested the same method in a class on the iPhone and it worked, and gave me the appropriate coordinates. What am I doing wrong?
The .h file:
#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface InterfaceController : WKInterfaceController
#end
The .m file:
#import "InterfaceController.h"
#interface InterfaceController()
#end
#implementation InterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
}
- (void)willActivate {
// This method is called when watch view controller is about to be visible to user
[super willActivate];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
[super didDeactivate];
}
- (IBAction)showLocation {
NSString * geoLoc = [NSString stringWithFormat:#"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
NSLog(geoLoc);
}
#end
Before you can get any location updates to your watch app extension you will need to authorize location updates in your iPhone app. If you haven't authorized location updates in your iPhone app, then your watch extension will not get any location updates. Also, I am pretty sure you need to set the permission to always allow for location updates [CLLocationManager requestAlwaysAuthorization]. I don't think it will work if you use [CLLocationManager requestWhenInUseAuthorization], though I am not 100% sure about the permissions.
In Xcode, you want use the Debug menu to simulate a location that's either pre-set or use a GPX file as the location source.
In the CLLocationMananager documentation, the location property states
The value of this property is nil if no location data has ever been retrieved.
That means that you need to call [self.locationManager startUpdatingLocation] in order to get a valid location. But there a could things you need to do before that will work.
First of all you will need to request authorization by calling [self.locationManager requestAlwaysAuthorization].
When authorization is approved or declined, the delegate method locationManager:didChangeAuthorizationStatus: will be called.
If the authorization status is kCLAuthorizationStatusAuthorizedAlways than you can call [self.locationManager startUpdatingLocation].
Then anytime the location is updated, the delegate method
locationManager:didUpdateLocations: will be called so you can update your UI with the new location.
You are not supposed to request location data within a WatchKit Extension.
From Apple Watch Human Interface Guidelines:
“Avoid using technologies that request user permission, like Core
Location. Using the technology from your WatchKit extension could
involve displaying an unexpected prompt on the user’s iPhone the first
time you make the request. Worse, it could happen at a time when the
iPhone is in the user’s pocket and not visible.”
I am using this code
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8)
{
[locationManager requestAlwaysAuthorization];
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
and to display in wkinterfaceMap i use this code
CLLocationCoordinate2D mapLocation = CLLocationCoordinate2DMake([latitude floatValue],[longitude floatValue]);
//
MKCoordinateSpan coordinateSpan = MKCoordinateSpanMake(1, 1);
[self.mapkit addAnnotation:mapLocation withPinColor: WKInterfaceMapPinColorPurple];
[self.mapkit setRegion:(MKCoordinateRegionMake(mapLocation, coordinateSpan))];

iOS 8 MKMapView User Location Request Failure

I have been trying to move my iOS7 app with MKMapview to support iOS8. However I couldn't get the new request for users to share their locations to work properly. I create my MKMapView on a storyboard and the delegate is set and works perfectly on iOS7. Here is what I've added to support iOS8 Location sharing:
myMapView.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface myMapView : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) CLLocationManager *locationManager;
myMapView.m
//Code omitted
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
//Code omitted
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if(IS_OS_8_OR_LATER) {
//[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
}
[self.mapView setShowsUserLocation:YES];
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = self.locationManager.location.coordinate.latitude;
region.center.longitude = self.locationManager.location.coordinate.longitude;
region.span.latitudeDelta = 0.0187f;
region.span.longitudeDelta = 0.0137f;
[self.mapView setRegion:region animated:YES];
_initialPosition = NO;
}
Also I have set NSLocationAlwaysUsageDescription key and its value in my InfoPlist, which shows the correct message when prompting the user to share their location.
Unfortunately the delegate function -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations never gets called. Although each time the viewController gets loaded the [self.locationManager startUpdatingLocation] is called, but the delegate does not seem to respond to it. Is there a problem of how I set the delegate or is there something else I am missing here?
UPDATE: It seems also that my gpx file is not being called on launch. I have cleared and reloaded my location file, even changed to a default location, but no location is found: Domain=kCLErrorDomain Code=0
UPDATE 2: Here is a SS from the settings that I have actually succeeded with the user request, but fail to get/update location no matter how much I refresh.
(source: barisaltop.com)
Thanks!
I had the same problem a few days ago. The solution was adding the string keys NSLocationAlwaysUsageDescription (for [CLLocationManager requestAlwaysAuthorization]) or NSLocationWhenInUseUsageDescription (for [CLLocationManager requestWhenInUseAuthorization]) to your Supporting Files/Info.plist
You can also edit the source code of the Info.Plist with Right click > open as > Source code and add these lines:
<!-- for requestAlwaysAuthorization -->
<key>NSLocationAlwaysUsageDescription</key>
<string>Explain for what are you using the user location</string>
<!-- for requestWhenInUseAuthorization -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Explain for what are you using the user location</string>
Hope this helps.
Finally I have succeeded to run my gpx file on the simulator. It seems that after installing Xcode 6 the first time, there might be a bug causing for gpx files to simulate. Here is how I overcame the problem:
I have deleted my app from the simulator
Under App->Capabilities enabled Background Modes->Location updates
Run the app and let it install on simulator
Allow access, and I was able to locate the user with GPX
Afterwards I disabled Location Updates.
I don't know why, but this did the trick for me.

iOS: Get current location coordinates without using MKMapView

I'd like to be able to get my current user's location without actually having a map view on my view controller.
At the moment I do have a map view and get the user location by calling one of the delegate methods....
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
userlatitude = userLocation.location.coordinate.latitude;
userlongitude = userLocation.location.coordinate.longitude;
}
CLLocationManager is the class that is responsible for keeping user's location values. CLLocationManagerDelegate is another class that gets real time location data from iDevice's GPS and notifies CLLocationManager instance about the change in location and various other events, via it's delegate methods. It would be very helpful if you would read the related documentation.
You must implement CLLocationManagerDelegate protocol inside your class.
You must also have CLLocationManager instance within your class that should monitor the location.
In your project, you must also add Core Location framework in Link Binaries section.
The simplest way would be:
Your .h file:
#interface MyViewController : UIViewController<CLLocationManagerDelegate>
{
CLLocation * currentLocation;
CLLocationManager * locationManager;
}
#end
Your .m file:
- (void) viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
//remember to stop before you are done, either here or in view disappearance.
- (void) dealloc
{
[locationManager stopUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
currentLocation = (CLLocation *)[locations lastObject];
}
Easily, use CCLocationManager instead of the MKMapKit::userLocaiton method.
Take a look at the "LocateMe" sample project on developer.apple.com.

App runs fine without method, but I thought it required the method to function properly

I have a location app that had the following method in the header of the ViewController.m file for the past couple of days:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
However, I just deleted the above out of my code and the app still runs 100% fine. I don't understand how this is possible when the xcode documentation clearly says that the purpose of this method is to "tell the delegate when new location data is available."
The only thing I can think of is that it says "new location data" and that the above method is already setup in the CoreLocation.h file that I imported, and therefore already available for my use and has already stored the data.
Just want to make sure I understand the theory behind all of this before I move on.
Thank you for the help in clearing this up.
Here is my entire ViewController.m code(with the method still included):
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#interface ViewController () <CLLocationManagerDelegate>
//This tells the delegate that new location data is available. Manager is the object that updates the event, and the locations object is where the array of location data is stored.
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.gpsLM = [[CLLocationManager alloc]init];
NSLog(#"Location services enabled: %u",[CLLocationManager authorizationStatus]);
[self.gpsLM startUpdatingLocation];
self.gpsLM.delegate = self;
CLLocation * currentLocation = self.gpsLM.location;
NSLog(#"Your current location is: %#", currentLocation);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(IBAction)gpsButton{
CLLocation * currentLocation = self.gpsLM.location;
self.gpsLabel.text = [NSString stringWithFormat:#"Your Location is %#", currentLocation];
NSLog(#"Location services enabled: %u",[CLLocationManager authorizationStatus]);
NSLog(#"Your current location is: %#", currentLocation);
}
#end
iOS checks if your class is capable of receiving the data with something like:
if ( [delegate respondsToSelector:#selector(didUpdateLocations:)] ){
[delegate performSelector:#selector(didUpdateLocations:) withArgs:....]
}
So if your delegate doesn't implement the method, then it doesn't attempt to send it.

Resources