I have a code in a UIViewController that starts the location update:
[locationManager startUpdatingLocation];
Is working perfectly. But I need every time you exit this screen it stops updating the location and start again when I return.
The first time it for updates. In other times it does not stop.
Code for exit from view:
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
Ihave tried also: (without success too)
[locationManager stopMonitoringSignificantLocationChanges];
[locationManager stopUpdatingHeading];
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
locationManager = nil;
It always update. But from the second time not stop update.
didUpdateLocation code:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
[self addingMarkerUser];
}
You should put your code in the viewDidAppear and i suppose in your [self addingMarkerUser] you use something like this without the stop (if not, please provide the code) :
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:_currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (!(error)) {
//do something with the data.
//then stop the update.
[locationManager stopUpdatingLocation];
}
}];
If you do like that, every time your view appear, the location will start the update then stop once the data retrieve.
Related
In my current project.
I need user's location at every 50 meter user move.
So Basically After open application every 50 meter change I need user location for call web service in Objective c. Also i want same process run when application is in background state.
Thanks in advance
You have to make object of CLLocationManager when application starts and set it's delegate
Add the below code to get user's current location
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
Now add the delegate of CLLocationManagaer that is didUpdateToLocation and add the following code in that.
CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
if(meters==50)
{
// CALL YOU WEBSERVICE
}
set your location track in
//create location manager object
locationManager = [[CLLocationManager alloc] init];
//there will be a warning from this line of code
[locationManager setDelegate:self];
//and we want it to be as accurate as possible
//regardless of how much time/power it takes
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//set the amount of metres travelled before location update is made
[locationManager setDistanceFilter:50];
and add
if ([CLLocationManager locationServicesEnabled]) {
[self.locationManager startUpdatingLocation];
}
Update
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *location = locations.lastObject;
NSLog(#"%#", location.description);
//In here you get all details like
NSLog(#"latitude = %#",location.coordinate.latitude);
NSLog(#"longitude = %#",location.coordinate.longitude);
NSLog(#"altitude = %#",location.altitude);
NSLog(#"horizontalAccuracy = %#",location.horizontalAccuracy);
NSLog(#"verticalAccuracy = %#",location.verticalAccuracy);
NSLog(#"timestamp = %#",location.timestamp);
NSLog(#"speed = %#",location.speed);
NSLog(#"course = %#",location.course);
}
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 need once the app is launch, to check the location and send it to the server. After it, i need to check the location every kilometer.
So when i started the location update, i set the distanceFilter to none and on the first location receive, i changed it to 1 kilometer.
//If the location update is denied
if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied)
[ self locationUpdateDenied:basicViewController];
else if ([CLLocationManager locationServicesEnabled]) {
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.distanceFilter=kCLDistanceFilterNone;
//In ViewDidLoad
if([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[_locationManager startUpdatingLocation];
}
The first location receive:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
if (locations>0) {
[_locationManager setDistanceFilter:1000.0f];
CLLocation *location = [locations objectAtIndex:0];
[User sharedInstance].latitude=location.coordinate.latitude;
[User sharedInstance].longitude=location.coordinate.longitude;
/* if (!_delegate) {
[_delegate userLocationUpdated];
}*/
}
}
the problem it keeps checking the location. The location isn't changing but it still gets to the didUpdateLocations. It like the distanceFilter isn't changing.
should i need to stop the location update and reactive it with the kilometer distanceFilter?
From the documentation i presume that you can set the distanceFilter property before you start the location service since you will be called immediatley after you start the service with startUpdatingLocation with a first location.
[manager setDistanceFilter:1000.0];
[manager startUpdatingLocation]; // will call didUpdateLocations immediatley
// with the current location
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 trying to use location monitoring in my app. I can set my location and reverseGeocode the location I want to monitor. the didUpdateToLocation delegate method works fine, and updates continuously but the didStartMonitoingForRegion delegate never gets called, nor do the didExitRegion nor didEnterRegion.
Any suggestions?
- (IBAction)setLocation:(UIButton *)sender {
if(!self.locationManager) self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:10]; // Update again when a user moves distance in meters
[self.locationManager setPurpose:#"Set location based alerts if switch is on"];
self.plugLocation=nil; //reset to nil so didUpdateToLocation will update it
self.distanceLabel.text=[NSString stringWithFormat:#"%d",0];
[self.locationManager startUpdatingLocation];
if ( ![CLLocationManager regionMonitoringAvailable] || ![CLLocationManager regionMonitoringEnabled] ){
NSLog(#"Location monitoring not Unavailable");
}else {
}
}
-(void)setPlugLocation:(CLLocation *)plugLocation{
//
if (!_plugLocation) _plugLocation=[[CLLocation alloc]init];
_plugLocation=plugLocation;
if (_plugLocation) {
[self setRegion:plugLocation radius:20 name:self.plugName];
[self reverseGeocode:self.plugLocation];
NSLog(#"setPlugLocation %#", [self.plugLocation description]);
}
}
-(void)setRegion:(CLLocation *)center radius:(double)meters name:(NSString*)name{
CLLocationCoordinate2D plug2D;
plug2D.latitude=center.coordinate.latitude;
plug2D.longitude=center.coordinate.longitude;
CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:plug2D radius:meters identifier:name];
[self.locationManager startMonitoringForRegion:region desiredAccuracy:kCLLocationAccuracyBest];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
self.latitudeLabel.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.latitude];
self.longitudeLabel.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.longitude];
if (self.plugLocation == nil)self.plugLocation = newLocation;
if (self.plugLocation!=nil) {
CLLocationDistance distanceBetween = [newLocation distanceFromLocation:self.plugLocation];
NSLog(#"didUpdateToLocation Distance from plug=%f",distanceBetween);
self.distanceLabel.text=[NSString stringWithFormat:#"%f",distanceBetween];
}
}
-(void)reverseGeocode:(CLLocation *)coordinates;{
if (!self.plugGeo) self.plugGeo = [[CLGeocoder alloc] init];
[self.plugGeo reverseGeocodeLocation:coordinates completionHandler:^(NSArray *placemarks, NSError *error) {
if (error==nil&&[placemarks count]>0) {
CLPlacemark *placemark=[placemarks objectAtIndex:0];
NSLog(#" setPlugLocation geocodeAddressString %#",placemark);
//should also transfer back to plug detail and save
self.locationLabel.text=[NSString stringWithFormat:#"%# %#\n%#, %#", placemark.subThoroughfare, placemark.thoroughfare, placemark.locality,placemark.postalCode];
[self sendAlertMessage:[NSString stringWithFormat:#"%# %#\n%#, %#", placemark.subThoroughfare, placemark.thoroughfare, placemark.locality,placemark.postalCode] title:#"Success"];
}else {
NSLog(#" setPlugLocation couldn't geoCode address %#",error);
}
}];
}
Are you using the simulator to test your application? Something that I've found is that the simulator is completely unreliable for region exit/enters. Try compiling the project on your device by plugging it in and changing from iPhone Simulator to your iOS device. You can then unplug your device and run your app from your phone to test it.
Why doesn't the simulator work for regions? Regions are mostly determined by Apple's hidden algorithm using Wi-Fi, cell towers, and other applications on the phone requesting location. Seeing as a simulator doesn't use Wi-Fi or cell towers... region monitoring is going to be pretty impossible.
It's likely your code is fine (I see no glaring errors), but the simulator is giving you bad results. Try it on your device and let us know if it does the same thing.