locationManager is not updating the Location - ios

i am using this code to get the Location ,using simulator , but its not giving me any output .
also if someone suggest me a solution of this or a better alternative solution.\
-(void)viewDidAppear:(BOOL)animated
{
_locationManager.delegate=self;
[_locationManager startUpdatingLocation];
[self.geoCoder reverseGeocodeLocation: _locationManager.location completionHandler:
^(NSArray *placemarks, NSError *error) {
if (error) {
return;
}
if (placemarks && placemarks.count > 0)
{
CLPlacemark *placemark = placemarks[0];
NSDictionary *addressDictionary =
placemark.addressDictionary;
NSString *address = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStreetKey];
NSString *city = [addressDictionary
objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStateKey];
NSString *zip = [addressDictionary
objectForKey:(NSString *)kABPersonAddressZIPKey];
NSString *Countrynsme = [addressDictionary
objectForKey:(NSString *)kABPersonAddressCountryKey];
_requestorAddressText.Text = address;
_requestorCityText.text = city;
_requestorPostalText.text = zip;
_CountryrequestorText.text = Countrynsme;
_requestorStateText.text = state;
}
}];
[_locationManager stopUpdatingLocation];
}

CLLocationManager is an asynchronous API. You need to wait for the result of CLLocationManager before you geocode the location.
Start listening for location manager updates using the CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSTimeInterval interval = [newLocation.timestamp timeIntervalSinceNow];
if (interval < 0) {
interval = -interval;
}
// Reject stale location updates.
if (interval < 30.0) {
// Start geocoding
[geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
// Use geocoded results
...
}];
}
// If you're done with getting updates then do [manager stopUpdatingLocation]
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
// Handle error. Perhaps [manager stopUpdatingLocation]
}
Then viewDidAppear just bootstrap's the location lookup:
- (void)viewDidAppear {
// PS: You're missing a call to [super viewDidAppear]
[super viewDidAppear];
// Start lookup for location
_locationManager.delegate=self;
[_locationManager startUpdatingLocation];
}
PS: In dealloc don't forget to stop updating location, cancel geocode and nil the delegates for locationManager.

Related

Delay in Corelocation

I've created a helper class for my location needs so i don't violate the DRY principle. The class looks like this:
Location.h
#interface Location : NSObject <CLLocationManagerDelegate>{
CLLocationManager *manager;
CLGeocoder *geocoder;
CLPlacemark *placemark;
}
-(float)latitude;
-(float)longitude;
-(NSString *)postalcode;
Location.m
#implementation Location{
float latitude;
float longitude;
NSString *postalcode;
}
-(id)init{
NSLog(#"Hallo");
[self setupLocationManager];
return self;
}
-(float)latitude{
return latitude;
}
-(float)longitude{
return longitude;
}
-(NSString *)postalcode{
return postalcode;
}
-(void)setupLocationManager{
manager = [[CLLocationManager alloc] init];
[manager requestWhenInUseAuthorization];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;
manager.distanceFilter = 100;
[manager startUpdatingLocation];
geocoder = [[CLGeocoder alloc] init];
}
#pragma mark - CLLocationManagerDelegate Methods
- (void)locationManager:(CLLocationManager *)manager didFailWithError: (NSError *)error
{
NSLog(#"Error: %#", error);
NSLog(#"Failed to get location! :(");
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"Location: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
latitude = currentLocation.coordinate.latitude;
longitude = currentLocation.coordinate.longitude;
}
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
postalcode = [NSString stringWithFormat:#"%#",placemark.postalCode];
/*
self.address.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
*/
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
}
#end
When i in my ViewController tries to create an instance of Location and set latitude and longitude labels, in the viewDidLoad method, the labels are sat to 0.00000.
Apparently it takes around half a second for Location to get the coordinates.
I've tried using
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self setCoordinateLabels];
});
But that just seems very hacky and can't possibly be the best practise? So is there any way i could do this a better way?
Well - that is very hacky. Why don't you forward your delegate methods call?
locationManager:didUpdateToLocation:
(Btw. this is a legacy function)
Tells you when the first location is set. You can just have an array of delegates on your Location class and call every delegate when it's time.
Here is an example with blocks:
static NSMapTable *listenerBlocks;
+ (void)addListener:(NSObject *)listener listenerBlock:(void (^)())listenerBlock
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
listenerBlocks =
[NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory
valueOptions:NSMapTableStrongMemory];
});
if (listenerBlock && listener) {
[listenerBlocks setObject:listenerBlock forKey:listener];
}
}
+ (void)removeListener:(NSObject *)listener
{
if (listener) {
[listenerBlocks removeObjectForKey:listener];
}
}
In your locationManager:didUpdateToLocation: you then just call
NSArray *allBlocks = [[listenerBlocks objectEnumerator] allObjects];
for(void (^listenerBlock)(NSString *) in allBlocks)
{
listenerBlock();
}
at the end
In the class that needs updates for the labels (e.g. myLabel):
[Location addListener:self listenerBlock:^{
dispatch_async(dispatch_get_main_queue(),^{
//myLabel.text = //... update your label here
[self setCoordinateLabels]; // as from your code above..
});
}];

Location Issue in iPhone Device

I want to detecting user's current location in my app.I am using objective c.It's working fine in simulator but while testing on device below error comes.
didFailWithError: Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"
Please Help me to solve this issue.I am using Lat long value for find out place mark in my application.
if(version<8.0)
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
else
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
}
Here are delegate method
- (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 *longitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
NSString *latitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation: locationManager.location completionHandler:
^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSString *placemark_str = [placemark locality];
subAdminArea.text=placemark.subAdministrativeArea;
NSString *are_str = [placemark subLocality];
subAdminArea.text=placemark.subAdministrativeArea;
NSString *location_str=[NSString stringWithFormat:#"%#,%#",are_str,placemark_str];
[[NSUserDefaults standardUserDefaults]setValue:location_str forKey:#"Location"];
NSLog(#"place mark str: %#",placemark_str);
}];
}}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"%#", [locations lastObject]);
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation: [locations lastObject] completionHandler:
^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSString *placemark_str = [placemark locality];
NSString *are_str = [placemark subLocality];
NSString *location_str=[NSString stringWithFormat:#"%#,%#",are_str,placemark_str];
[[NSUserDefaults standardUserDefaults]setValue:location_str forKey:#"Location"];
}];}
- (void)requestAlwaysAuthorization{
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
// If the status is denied or only granted for when in use, display an alert
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusDenied) {
NSString *title;
title = (status == kCLAuthorizationStatusDenied) ? #"Location services are off" : #"Background location is not enabled";
NSString *message = #"To use background location you must turn on 'Always' in the Location Services Settings";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Settings", nil];
[alertView show];
}
// The user has not enabled any location services. Request background authorization.
else if (status == kCLAuthorizationStatusNotDetermined) {
[locationManager requestAlwaysAuthorization];
}}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 1) {
// Send the user to the Settings for this app
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}}
I have also update my plist file with NSLocationAlwaysUsageDescription->String & NSLocationWhenInUseUsageDescription -> String.
Thank You.
1) check that you actually have a valid WiFi and 3G connection
if you do then
2) go to settings and reset your location services
3) then reset your network settings

CoreLocations reverseGeocodeLocation getting it to run / loop once per minute only

HiallI am using Corelocation and updating basic long, lat etc to a view as many time per second as possible, this is what I want, but I now have brought in reverseGeocodeLocation which I only want that to run / geocode the location once per minute. It too at the moment is updating as much as possible which Apple says is bad and only wants it to update once per minute.
Can someone please show me how I do this? (keep my main corelocation updates coming in as much as possible, but have my reverseGeocodeLocation run once per minute.)
I have tried multiple differen ways to limit the amount reverseGeocodeLocation runlike with a timer, if statements and dispatch_after without success, these other ways I have tried are below, I'm not sure if I need to do something like pause the code somehow while it does the Geocode or ??? etc. My corelocation code is pretty stock standard Apple example code.
Any help would be great!
//code below not showing all code but related parts etc
.h
#interface ViewController : UIViewController <CLLocationManagerDelegate>
//I set other standard property outlets for location, locationManager, labels etc
#property (nonatomic, strong) NSDate *reverseGeoLastUpdate; //my 60second reversegeoupdates
.m
#implementation ViewController {
NSTimer *timer;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self startStandardUpdates];
}
- (void)startStandardUpdates {
if (nil == _locationManager)
_locationManager = [[CLLocationManager alloc] init];
geocoder = [[CLGeocoder alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[_locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
NSLog(#"eventDate timeIntervalSinceNow = %f", [eventDate timeIntervalSinceNow]);
if (abs(howRecent) < 15.0) {
self.coordinateLat.text = [NSString stringWithFormat:#"%f", location.coordinate.latitude];
//my timer code for reverseGeocodeLocation, trying to get to to run once at the start then every 60 seconds after
//this fires once at the start because self.reverseGeoLastUpdate == nil with no errors but my views onscreen label never actually gets updated with the data from the geoserver, and also the loop does not repeat when [self.reverseGeoLastUpdate timeIntervalSinceNow] > 60???????
if( [self.reverseGeoLastUpdate timeIntervalSinceNow] > 60 || self.reverseGeoLastUpdate == nil ){
NSLog(#"Resolving the Address: Loop run %d", _amountofruns++);
[geocoder reverseGeocodeLocation:_location completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
_address1.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#\n",
placemark.subThoroughfare, placemark.thoroughfare,
//other 4 place marker calls here
];
} else {
NSLog(#"%#", error.debugDescription);
}
}];
self.reverseGeoLastUpdate = [NSDate date];
}
}
When I tried a NSTimer in place of where the "//my timer" code is in the method above but get
"Error Domain=kCLErrorDomain Code=8 "The operation couldn’t be completed".
NSTimer scheduledTimerWithTimeInterval: 60.0
target: self
selector:#selector(onTick:)
userInfo: nil
repeats:YES];
-(void)onTick:(NSTimer *)timer {
[geocoder reverseGeocodeLocation:_location completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
_address1.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#\n",
placemark.subThoroughfare, placemark.thoroughfare,
//other 4 place marker calls here
];
} else {
NSLog(#"%#", error.debugDescription);
}
}];
When I tried
dispatch_after way it fires and label gets updated but once it fires it continuously fires every frame, and couldn't work out how to get it to go once per 60 seconds.
double delayInSeconds = 60.0;
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(delayTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^(void){
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
_address1.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#\n",
placemark.subThoroughfare, placemark.thoroughfare,
//other 4 placemarks
];
} else {
NSLog(#"%#", error.debugDescription);
}
}];
});
Any help with figuring out how to do this properly would be great
Your first code is almost correct, but you need to account for the fact that the reverse geocode will complete on a background thread and that you should only update the UI on the main queue.
if(self.reverseGeoLastUpdate == nil || [self.reverseGeoLastUpdate timeIntervalSinceNow] > 59 ) {
self.reverseGeoLastUpdate = [NSDate date];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
dispatch_async(dispatch_get_main_queue(), ^{
self.address1.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#\n",
placemark.subThoroughfare, placemark.thoroughfare,
//other 4 place marker calls here
];
});
} else {
NSLog(#"%#", error.debugDescription);
}
}];
}
}
Also, try to get out the habit of using _ instead of self to access properties unless you deliberately want to bypass a setter/getter

Location Service doesn't provide all data in iOS SDK

It shows me (null) (null),Ahmedabad Gujarat (null) (null) when following code executes.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
_CurrentLocation = newLocation.coordinate;
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error)
{
for (CLPlacemark * placemark in placemarks)
{
NSString *addressTxt = [NSString stringWithFormat:#"%# %#,%# %# %# %#",
[placemark subThoroughfare],[placemark thoroughfare],
[placemark locality], [placemark administrativeArea], [placemark subLocality],[placemark subAdministrativeArea]];
NSLog(#" >> %#",addressTxt);
self.strLocation = [placemark locality];
}
}];
}
How to get other values ? Is location service will not provide these data in my area ?
And if not then any alternative to get this data ?

I can't update location IOS

I'm trying to get the city name of my location, I use this code:
- (void)viewDidLoad
{
[super viewDidLoad]; CLLocationManager *locationManager =[[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//implementamos los metodos delegados de CLLocationManager.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// this creates a MKReverseGeocoder to find a placemark using the found coordinates
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSString * location = ([placemarks count] > 0) ? [[placemarks objectAtIndex:0] locality] : #"Not Found";
_ciudadLabel.text=location;
}];
}
// this delegate method is called if an error occurs in locating your current location
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"locationManager:%# didFailWithError:%#", manager, error);
}
But when I execute the application, the message that says if I want to allow to get my location disapear suddenly and don't execute:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// this creates a MKReverseGeocoder to find a placemark using the found coordinates
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSString * location = ([placemarks count] > 0) ? [[placemarks objectAtIndex:0] locality] : #"Not Found";
_ciudadLabel.text=location;
}];
}
why the location doesn't start?
Thanks

Resources