I am currently working on a location based ios application. I am using didupdatelocation delegate method for showing user's current location. It works fine when I connect my device to internet. But when I disconnect the internet, it behaves strange and didupdatelocation is not getting called further. Please give a solution.
EDITED with code details
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc]init]; // initializing locationManager
locationManager.delegate = self; // we set the delegate of locationManager to self.
locationManager.desiredAccuracy = kCLLocationAccuracyBest; // setting the accuracy
[locationManager startUpdatingLocation]; //requesting location updates
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"There was an error retrieving your location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[errorAlert show];
NSLog(#"Error: %#",error.description);
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *crnLoc = [locations lastObject];
latitude.text = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.latitude];
longitude.text = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.longitude];
altitude.text = [NSString stringWithFormat:#"%.0f m",crnLoc.altitude];
speed.text = [NSString stringWithFormat:#"%.1f m/s", crnLoc.speed];
}
#ANSHAD per your comment, if you are using an older iPad without GPS, the only way you can get location data is with WiFi so if you turn off WiFi, you will not get location updates. If you want GPS without WiFi you can buy an external GPS module see here
You can use the base GPS of the iPhone which works without the internet too. To access it you need to use the CoreLocation framework.
You can refer to this : CoreLocation methods to use the GPS data.
Let me know if any other help required.
Related
Can I detect whether a user moved to another country?
(Not using Locale.current)
The location detection should be running in background.
I'm hoping to do something like this.
Eg. A user from US leaves the country to UK. Then, when the user reach UK, i am able to detect it at the background and send notification.
You should in your Info.plist, set allowsBackgroundLocationUpdates to YES, this you can search google, and lots of answer for adapt iOS 9.
First you can use CLLocationManager to get the location:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib .
//delegate
self.locationManager.delegate = self;
//The desired location accuracy.
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//Specifies the minimum update distance in meters.
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.purpose = #"To provide functionality based on user's current location.";
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
UIAlertView* av = [[UIAlertView alloc] initWithTitle:#"update" message:[NSString stringWithFormat:#"didUpdateToLocation: newLocation: %# old:%#",newLocation,oldLocation] delegate:nil cancelButtonTitle:#"cancel" otherButtonTitles:#"ok", nil nil];
[av show];
}
Secondly, you can use CLGeocoder to get country or city.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// get city name
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *array, NSError *error)
{
if (array.count > 0)
{
CLPlacemark *placemark = [array objectAtIndex:0];
NSString *city = placemark.locality;
}
else if (error == nil && [array count] == 0)
{
NSLog(#"No results were returned.");
}
else if (error != nil)
{
NSLog(#"An error occurred = %#", error);
}
}];
}
You can give a duration to get location per duration:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
newLocation = [locations lastObject];
double lat = newLocation.coordinate.latitude;
double lon = newLocation.coordinate.longitude;
NSLog(#"lat:%f,lon:%f",lat,lon);
if (!self.deferringUpdates) {
CLLocationDistance distance = 500;
NSTimeInterval time = 20;
[locationManager allowDeferredLocationUpdatesUntilTraveled:distance
timeout:time];
self.deferringUpdates = YES;
}
}
You can create UNNotificationRequest with exit UNLocationNotificationTrigger.
UNNotificationRequest
A UNNotificationRequest object is used to schedule a local notification and manages the content for a delivered notification. A notification request object contains a UNNotificationContent object with the contents of the notification. It also contains the UNNotificationTrigger object that specifies the conditions that trigger the delivery of the notification. For a delivered notification, you use these objects to fetch information about the notification.
UNLocationNotificationTrigger
A UNLocationNotificationTrigger object causes the delivery of a notification when the device enters or leaves a specified geographic region. Use this object to specify the region information needed to trigger the notification. Location triggers can fire once or they can fire multiple times.
Apps must request access to location services and must have when-in-use permissions to use this class. To request permission to use location services, call the requestWhenInUseAuthorization() method of CLLocationManager before scheduling any location-based triggers.
Flow
Each time user opens app, check his local country and define location trigger
let region: CLRegion = <your code defining country region>
region.notifyOnEntry = false
region.notifyOnExit = true
let trigger = UNLocationNotificationTrigger(region: region, repeats: false)
and using that trigger reschedule notification request (UNNotificationRequest).
When trigger fires (user leaves region) — app will present local notification, and if user taps on it, app starts, and if you add handler on local notification open you can notify your server about user moving away and check his new country and do what you need to do.
I'm trying to use the CLLocationManager framework in my iOS project to access the user's location but when I call
[locationManager startUpdatingLocation]
neither locationManager:didUpdateLocations: or locationManager:didFailWithError: are getting called.
//myViewController.h
#interface myViewController : UITableViewController <CLLocationManagerDelegate>
#end
//myViewController.m
#implementation myViewController{
CLLocationManager *locationManager;
}
//edit
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
}
//finish edit
-(void)getLocation
{
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)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 didUpdateLocations:(NSArray *)locations
{
CLLocation *newLocation = locations[[locations count] -1];
CLLocation *currentLocation = newLocation;
NSString *longitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
NSString *latitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
if (currentLocation != nil) {
NSLog(#"latitude: %#", latitude);
NSLog(#"longitude: #"%#", longitude);
}else {
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[errorAlert show];
}
}
#end
Neither delegate method is being called despite what it says in the documentation:
"This method returns immediately. Calling this method causes the location manager to obtain an initial location fix (which may take several seconds) and notify your delegate by calling its locationManager:didUpdateLocations: method [...] In addition to your delegate object implementing the locationManager:didUpdateLocations: method, it should also implement the locationManager:didFailWithError: method to respond to potential errors."
Don't know how to debug the issue.
Thanks,
JA
Just add this in info.plist
NSLocationAlwaysUsageDescription --- I need Location
NSLocationWhenInUseUsageDescription --- I need Location
privacy - location usage description --- I need Location
Note that "I need Location" should be changed to describe your actual app's designed usage. It is communicated to the end user in the authorization message. (thanks #devios1)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=kCLDistanceFilterNone;
[locationManager requestWhenInUseAuthorization];
[locationManager startMonitoringSignificantLocationChanges];
[locationManager startUpdatingLocation];
Now it will call your didUpdateToLocation definitely.
for more details click here
You strongly need to check that you initialize CLLocationManager on main thread.
In other case you will not get updateLocation event.
I can't find such info in Apple docs but it works for me anyway.
Location Services work a bit differently starting in iOS 8.
Mainly, you need to add a key NSLocationWhenInUseUsageDescription to your Info.plist file, and add a description why your app need Location, such as "Location needed to ...".
Note that you might also have to check for iOS version. Only iOS 8 and up have the Location Manager listen to the requestWhenInUseAuthorization call.
The link below shows more details:
http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
Good luck!
With iOS 8.0 you need to call -[CLLocationManager requestWhenInUseAuthorization
] or -[CLLocationManager requestAlwaysAuthorization] first so the user gets asked to give your app permission to use the location.
You need to add below things to your project,
In plist of your project add these things:
Key: NSLocationAlwaysUsageDescription Type:String
Key: NSLocationWhenInUseUsageDescription Type:String
In the .m file with [locationManager startUpdatingLocation] add this condition :
if([locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
[locationManager requestAlwaysAuthorization];`
Then only your CLLocationManager delegate methods will get called.
I think you should check this link.You are not retaining the location manager object when declaring.
please give property to you object
#property(nonatomic, strong)
Why the CLLocationManager delegate is not getting called in iPhone SDK 4.0?
So if you are running in simulator don't forget to set location in simulator menu. It looks like if it is set to none nothing is called in delegate... I am not sure than if this can happen on real device too but probably it's simulator specific.
I had the following in my code base:
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if( status == kCLAuthorizationStatusAuthorizedAlways ) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.distanceFilter = 200;
}
}
Turns out that this was getting called in an infinite loop, because initializing a locationManager triggers this method for some reason? I had not realized that. I had put it there to catch when permissions were granted. Instead, I set up a location manager and started updating the location, but then this fired and replaced it with one that wasn't updating the location, and kept looping over and over.
Solution for me was just to add && !_locationManager to the if condition.
I have a location based app, all though the region is correct the app never moves to didEnterRegion or didExitRegion
for (int x = 0; x <= [[[TaskStore sharedStore] allTasks]count]-1; x++)
{
NSArray *tasks = [[TaskStore sharedStore] allTasks];
Task *selectedTask = [tasks objectAtIndex:x];
location.latitude = selectedTask.locationCoord.coordinate.latitude;
location.longitude = selectedTask.locationCoord.coordinate.longitude;
NSString* desiriedLoc = [selectedTask locationName];
CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter: location radius: 30.0 identifier: desiriedLoc];
NSLog(#"Entered new Location in Region %#", region);
[locManager startMonitoringForRegion:region];
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(#"didEnterRegion for %#",region.identifier);
UIAlertView *alr=[[UIAlertView alloc] initWithTitle:#"Reminder didEnterRegion"
message:region.identifier delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alr show];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(#"didExitRegion for %#",region.identifier);
UIAlertView *alr=[[UIAlertView alloc] initWithTitle:#"Reminder didExitRegion" message:region.identifier delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alr show];
}
Here is a string print out from my location:
Entered new Location with the coordinates Latitude: 51.509980 Longitude: -0.133700
and here is a string print out from the region:
Entered new Location in Region (identifier London) <+51.50998000,-0.13370000> radius 30.00m
As #verbumdei commented, the only way you will get the -didEnterRegion and -didExitRegion is to establish a CLLocationManagerDelegate. Set your view as the delegate and add those methods and you should see the update.
One thing to note, you are using a 30M radius, you will need to be quite approximate in your location if you want to trigger updates. This is fairly easy to do in the Simulator, but in real life usage (on device), 30M accuracy is a bit tougher. I would start with 100M and work your way down based on experience.
If you start monitoring while staying in the target region, nothing triggered.
Because it's not really an "didEnterRegion" event.
You don't seem to be setting
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
Without explicitly setting these properties, the specified events will not get fired.
I want to get the user's current location from my iPhone app. I want to show the user's current location like country name, latitude, longitude information in my app. And also i want to show the location in Google map also. I have tried Google search also, but can't get the exact answer. I have get the info that was to use CLLocationManager in my app to track the location. How do i use this? I have download one sample app from Apple Documents. Here is the link: https://developer.apple.com/library/ios/#samplecode/LocateMe/Introduction/Intro.html
Can you please help me on this? Thanks in advance.
1) I have get the info that was to use CLLocationManager in my app to track the location. How do i use this?
in .h file
#include <CoreLocation/CLLocationManagerDelegate.h>
#include <CoreLocation/CLError.h>
#include <CoreLocation/CLLocation.h>
#include <CoreLocation/CLLocationManager.h>
CLLocationManager * myLocationManager;
CLLocation * myLocation;
in .m file :-
-(void)findMyCurrentLocation
{
self.myLocationManager = [[[CLLocationManager alloc] init] autorelease];
[[self myLocationManager] setDelegate:self ];
[myLocationManager startUpdatingLocation];
double latitude=34.052234;
double longitude=-118.243685;
CLLocation *defaultLocation =[[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
[self setMyLocation:defaultLocation];
[defaultLocation release];
if( [CLLocationManager locationServicesEnabled] )
{
NSLog(#"Location Services Enabled....");
locationServicesEnabled=TRUE;
UIAlertView *alert = [ [UIAlertView alloc] initWithTitle:#"Information"
message:#"Fetching your current location."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil ];
[alert release];
}
else
{
NSLog( #"Location Services Are Not Enabled...." );
locationServicesEnabled=FALSE;
UIAlertView *alert = [ [UIAlertView alloc] initWithTitle:#"Information"
message:#"Location service is not enable. Please enable it from settings."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil ];
[alert release];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[self setMyLocation:newLocation];
NSString *tempLat = [ NSString stringWithFormat:#"%3.6f" , (newLocation.coordinate.latitude) ];
NSString *tempLong= [ NSString stringWithFormat:#"%3.6f" , (newLocation.coordinate.longitude)];
appDelegate.curlat = tempLat;
appDelegate.curlong = tempLong;
}
- (void)locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error
{
printf("\nerror");
UIAlertView *alert = [ [UIAlertView alloc] initWithTitle:#"Error"
message:#"Error while getting your current location."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil ];
[alert release];
}
2). I want to show the user's current location like country name information in my app.
For this you can to use Google's Reverse Geo coding OR MKReverseGeocoder
this should do most of it..
http://www.highoncoding.com/Articles/804_Introduction_to_MapKit_Framework_for_iPhone_Development.aspx
to get the information on the location you need to use MKReverseGeocoder
https://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKReverseGeocoder_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40008323
First create an instance of the MKMapView
To get user's latitude and longitude:
In your viewDidLoad
[yourMapView setShowsUserLocation:YES];
CLLocationCoordinate2D userCoord;
userCoord.latitude=map_view.userLocation.coordinate.latitude;
userCoord.longitude=map_view.userLocation.coordinate.longitude;
//NSLogging these on simulator will give you Cupertino or whatever location you set in location simulation.
And for country name you will need reversegeocoding you can look at the class reference here
https://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKReverseGeocoder_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40008323
OR
If MKReverseGeoCoding gets too complicated you can use Yahoo's reversegeocoder
http://where.yahooapis.com/geocode?q=%f,%f&gflags=R&appid=yourAppId, those 2 %f will be userCoord.longitude and userCoord.latitude.
Yes you can use CLGeoCoder. But CLGeaCoder will not provide accrurate location inforamtion outside of USA for other country like India etc. So better to use Google's Reverse Geo coding SVGeoCoder. SVGeoCoder have nice implementation to get location with goolePlaceAPI.
I am using both the simulator and my device to test this, but no matter what I do, didUpdateToLocation is never called. I have tried changing my location in the sim, turning off and then on again my location services on my phone to force the phone to search for a new location... nothing. In my viewDidLoad(), I have started the CLLocationManager as so:
CLLocationManager *manager = [[CLLocationManager alloc] init];
if (![CLLocationManager locationServicesEnabled])
{
UIAlertView *servicesDisabledAlert = [[UIAlertView alloc] initWithTitle:#"Location Services Disabled" message:#"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." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[servicesDisabledAlert show];
} else {
manager.desiredAccuracy = kCLLocationAccuracyBest;
manager.delegate = self;
[manager startUpdatingLocation];
}
and in the update location method I have this:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"NEW LOCATION! Accuracy:[%f]",newLocation.horizontalAccuracy);
}
Does anyone have any ideas why this isn't being called?
Did you add location delegate in your header file ?
I don't know if this is the issue but try
manager.desiredAccuracy = kCLLocationAccuracyKilometer;
or
manager.desiredAccuracy = kCLLocationAccuracyTenMeters;
instead of
manager.desiredAccuracy = kCLLocationAccuracyBest;
and see if that makes any change.
Setting desiredAccuracy to best timed out most of the times when I test my location dependent apps on my iPhone. Especially when you are indoors.