Current location is not being found on initial load or resume after multi-tasking. This is what I have:
ViewController.h
#interface ViewController : UIViewController <CLLocationManagerDelegate, ADBannerViewDelegate, BEMSimpleLineGraphDelegate>
ViewController.m
#interface ViewController (){
CLLocationManager *locationManager;
CLLocation *location;
CLLocationCoordinate2D coordinate;
int timeofday;
NSString *cityName;
NSMutableArray *ArrayOfValues;
}
#end
Further down:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateLabels) name:UIApplicationWillEnterForegroundNotification object:nil];
// set up coordinates for current location
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = (id)self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
location = [locationManager location];
}
Then my update labels method (which has other code that updates my view below this):
- (void)updateLabels
{
CLLocationCoordinate2D currentLocation = [location coordinate];
if (currentLocation.latitude) {
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error){
NSLog(#"Geocode failed with error: %#", error);
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
cityName = [NSString stringWithFormat:#"%# is currently",placemark.locality];
}];
[self updateLabels];
} else {
NSLog(#"Could not find the location.");
}
}
And here are the 2 delegate methods for cclocationmanager:
#pragma mark - CLLocationManagerDelegate
- (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;
[self updateLabels];
[locationManager stopUpdatingLocation];
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:currentLocation
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error){
NSLog(#"Geocode failed with error: %#", error);
return;
}
// CLPlacemark *placemark = [placemarks objectAtIndex:0];
}];
}
Try removing the call to stopUpdatingLocation. Also un-comment the log statement in didUpdateToLocation.
Be aware that the method locationManager:didUpdateToLocation:fromLocation: is deprecated in iOS 6. It might not even be called in iOS 7. You should be using `locationManager:didUpdateLocations:' instead.
Your call to updateLabels is using the value set in the member variable location. However your didUpdateToLocation method is not setting this value.
Put some breakpoints in your code and see where it triggers.
Note, for a weather application you do not need kCLLocationAccuracyBest, that takes way more time than coarser settings. You'll get your answer much quicker.
You are setting location, which I assume is a class level iVar, in ViewDidLoad.
location = [locationManager location];
I expect that the location manager at that point has no location.
Then, in the delegate call, you are updating a method level iVar :
CLLocation *currentLocation = newLocation;
This variable is never used, that I can see. Your updateLabels call once again refers to location which has never been updated.
CLLocationCoordinate2D currentLocation = [location coordinate];
Change the delegate to:
location = newLocation;
As #Duncan C stated, the delegate method you are using is deprecated, you should really be using locationManager:didUpdateLocations: in which case you would use:
location = [locations lastObject];
Related
I'm trying to implement longitude and latitude in my sample app. I use iPhone 5s device to test it. It doesn't show any effect on latitude and longitude labels on button actions.
Before compiling Xcode shows warning at line didUpdateToLocation: fromLocation: method as
"implementing deprecated method"
please help me with the suitable method which replaces this method for smooth working of the app
With Xcode 12.4 and for iOS 12.3 using objective c I'm trying to implement a simple location demo app which shows longitude and latitude. Below are my viewController.h and viewController.m files. And I've tried this below code from online tutorial AppCoda
viewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController :UIViewController<CLLocationManagerDelegate>
{
IBOutlet UILabel *lattitudeLabel;
IBOutlet UILabel *longitudeLabel;
IBOutlet UILabel *addressLabel;
}
- (IBAction)getCurrentLocation:(UIButton *)sender;
#end
viewController.m
#import "ViewController.h"
#interface ViewController ()
{
CLLocationManager *locationManager;
CLGeocoder *geocoder;
CLPlacemark *placemark;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc]init];
geocoder = [[CLGeocoder alloc] init];
}
- (IBAction)getCurrentLocation:(UIButton *)sender
{
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
NSLog(#"Error: Failed to get location");
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
longitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
lattitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
[locationManager stopUpdatingLocation];
NSLog(#"Resolving the Address");
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
self->placemark = [placemarks lastObject];
self->addressLabel.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
self->placemark.subThoroughfare, self->placemark.thoroughfare,
self->placemark.postalCode, self->placemark.locality,
self->placemark.administrativeArea,
self->placemark.country];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
}
#end
On clicking button get my location nothing is happening. It should actually update the co-ordinates besides Longitude: and Latitude: some float values..but it's not doing that..I'll ask please suggest me links to any tutorial web site or any GitHub project for location handling in iOS 12.3 and above in objective c...Thanks for the replies and suggested edits.
As the docs say, just use locationManager(_:didUpdateLocations:)
.
Swift 5
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Stop updates if this is a one-time request
manager.stopUpdatingLocation()
// Pop the last location off if you just need current update
guard let newLocation = locations.last else { return }
<... Do something with the location ...>
}
Objective-C
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
[manager stopUpdatingLocation];
CLLocation *newLocation = [locations lastObject];
if (newLocation) {
<... Do something with the location ...>
}
}
I hope this implementation for delegate method will help you.
works both on Mac and IOS. I used it to pinpoint current position for weather application.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations
{
if (locations.count > 0) {
// Location manager has nonempty array of readings
// We take the las one - the latest position determined
CLLocation *last = locations[locations.count - 1];
// Evaluate threshold distance to notice change
CLLocationDistance distance = LOCATOR_SENSITIVITY + 1;
if (previous) {
// calculate distance from previous location
distance = [last distanceFromLocation:previous];
}
// update previous location
previous = last;
if (distance > LOCATOR_SENSITIVITY) {
// If we moved far enough, update current position
currentLat = last.coordinate.latitude;
currentLon = last.coordinate.longitude;
// and notify all observers
// You can use delegate here, dispatch_async wrapper etc.
[[NSNotificationCenter defaultCenter]
postNotificationName:LocationIsChanged object:nil];
}
}
}
I am using below code for getting longitude and latitude , but it gives me diifferent values even if I am not moving from my place
locationmanager=[[CLLocationManager alloc]init];
geocoder=[[CLGeocoder alloc]init];
locationmanager.delegate=self;
locationmanager.desiredAccuracy=kCLLocationAccuracyBest;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[locationmanager requestWhenInUseAuthorization];
}
[locationmanager startUpdatingLocation];
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"error" message:#"Failed to get Location." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentlocation=newLocation;
if (currentlocation!=nil)
{
longitude=currentlocation.coordinate.longitude;
latitude=currentlocation.coordinate.latitude;
}
[geocoder reverseGeocodeLocation:currentlocation completionHandler:^(NSArray *placemarks, NSError *error) {
} ];
}
please guide me, I want same location, if I am not moving from my place.
Cellular network location gives an approximate area were the phone existing. It is based on the service providers tower.So current location will automatically changes a bit depending on network/gps location tracking/accuracy.
I recommend you to get location using distance filter, so until you are in that region your current address will remain same as location only updates for every X meters.
locationManager.distanceFilter = 100;//Your own distance
i.e.,
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
_locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
_locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[_locationManager startUpdatingLocation];
Hope this helps.
In ViewController.h file:
#interface ViewController : UIViewController<CLLocationManagerDelegate>
{
CLLocationManager *location;
}
In ViewController.m file:
- (void)viewDidLoad
{
location = [[CLLocationManager alloc] init];
location.delegate = self;
location.distanceFilter = 100;
[location requestWhenInUseAuthorization];
[location requestAlwaysAuthorization];
[location startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *locati = [locations lastObject];
float lat=locati.coordinate.latitude;
float lon=locati.coordinate.longitude;
NSLog(#"%f %f",lat,lon);
[location stopUpdatingLocation];
}
In your info.plist add :
Is there a way to determine specific places that users are currently in? I would like to show more than the current city or country they are in and instead show lakes, parks, and other things that if searched on a map would correspond to that location (i.e. Sears Tower, Downtown New York, Yellowstone Park). Also, if this is not possible can anyone provide an example showing the updated way of getting which city you are in? Im using Obj-c in Xcode, but I am having trouble doing this. Any help would be appreciated!
Here is the code I'm using so far:
Implementaion
CLLocationManager *locationManager;
ViewDidLoad
locationManager = [[CLLocationManager alloc] init];
Button
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
Void Method
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSLog(#"%#", currentLocation);
}
}
Pass the coordinates you receive from LocationManager to CLGeocoder
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:currentLocation completionHandler:
^(NSArray *placemarks, NSError *error) {
if ([placemarks count] > 0) {
CLPlacemark *placemark = placemarks[0];
NSLog(#"country is: %#", placemark.country );
}
}];
I'm trying to use core location in iOS 8 simulator, for that I added in my view an object of type 'MapKit View', In tab Atributtes inspector is checked the option show user location, In my project I'm using ARC, below is the structure of my code:
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MeuPrimeiroViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>{
IBOutlet MKMapView *mapView;
}
#property (nonatomic, strong) CLLocationManager *locationManager;
#end
ViewController.m
#synthesize locationManager;
- (void)viewDidLoad {
[super viewDidLoad];
if ([CLLocationManager locationServicesEnabled]) {
NSLog(#"CLLocationManager locationServicesEnabled == ON");
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Check for iOS 8 Vs earlier version like iOS7.Otherwise code will
// crash on ios 7
if ([locationManager respondsToSelector:#selector
(requestWhenInUseAuthorization)]) {
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
}else{
NSLog(#"CLLocationManager locationServicesEnabled == OFF");
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(#"It works this method is called");
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(#"Error: %#",[error description]);
}
In my info.plist file I add this key (NSLocationAlwaysUsageDescription) with this value (String).
If I go to attributes inspector and enable the checkbox (shows user location) I receive this error message, and core location methods are not called:
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
If I disable the checkbox, this message disappear, and core location methods not called again. I try to change the navigation to londom, try to change location to free run but nothing I tried worked, the methods do not continue to be called and never showed an empowering message to use core location. I believe I've already tried everything, anyone have any suggestions or a solution to this problem?
This is what i am doing for my app and working perfectly
- (void)startSignificantChangeUpdates {
if (nil == self.locationManager) {
self.locationManager = [[CLLocationManager alloc] init];
}
self.locationManager.delegate = self;
[self.locationManager startMonitoringSignificantLocationChanges];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation* location = [locations lastObject];
if (location) {
self.currentLocation = location;
NSString *latitude = [NSString stringWithFormat:#"%f", location.coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:#"%f", location.coordinate.longitude];
self.latLong = [NSString stringWithFormat:#"%#,%#",latitude, longitude];
}
if (!self.geocoder)
self.geocoder = [[CLGeocoder alloc] init];
[self.geocoder reverseGeocodeLocation:location completionHandler:
^(NSArray* placemarks, NSError* error){
if ([placemarks count] > 0) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
if (placemark.postalCode) {
self.currentZipCode = placemark.postalCode;
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"zipCodeFoundNotification" object:self.currentZipCode userInfo:nil];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:#"zipCodeFoundNotification" object:nil userInfo:nil];
}
}];
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status != kCLAuthorizationStatusAuthorized && status != kCLAuthorizationStatusNotDetermined) {
if (status == kCLAuthorizationStatusDenied){
self.currentZipCode = #"kCLAuthorizationStatusDenied";
} else if (status == kCLAuthorizationStatusRestricted) {
self.currentZipCode = #"kCLAuthorizationStatusRestricted";
}
}
}
I have a custom navbar with a locateButton that is visible in every view
When a user taps the locateButton, I would like to update lat and long on every view. I've got it working in one view at a time, with the following code.
ViewController.m
- (UIBarButtonItem *)locateButton {
[locationButton addTarget:self action:#selector(locationPressed:) forControlEvents:UIControlEventTouchUpInside];
}
- (IBAction)locationPressed:(id)sender {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (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) {
latLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
longLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
// Stop Location Manager
[locationManager stopUpdatingLocation];
// Reverse Geocoding
NSLog(#"Resolving the Address");
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
addressLabel.text = [NSString stringWithFormat:#"%#, %#",
placemark.locality,
placemark.administrativeArea];
addressLabel.numberOfLines = 0;
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
I'm trying to add a singleton to accomplish this.
In Location.h
// Location.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface Location : NSObject <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager* locationManager;
+ (Location*)sharedSingleton;
#end
Then in Location.M
// Location.m
#import "Location.h"
#implementation Location
#synthesize locationManager;
- (id)init {
self = [super init];
if(self) {
self.locationManager = [CLLocationManager new];
[self.locationManager setDelegate:self];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
[self.locationManager setHeadingFilter:kCLHeadingFilterNone];
[self.locationManager startUpdatingLocation];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//do any more customization to your location manager
}
return self;
}
+ (Location*)sharedSingleton {
static Location* sharedSingleton;
if(!sharedSingleton) {
#synchronized(sharedSingleton) {
sharedSingleton = [Location new];
}
}
return sharedSingleton;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
[locationManager stopUpdatingLocation];
}
#end
How do I get my - (IBAction)locationPressed:(id)sender in another view let's say HomeViewController.m to call this locationManager method and also update the singleton value?
You might consider a singleton as your location manager and location manager delegate. There are a bunch of stackoverflow questions about creating singletons like this one: Singleton in iOS 5?.
Then when your user clicks that button, your singleton class will be called and updated and other views will look at that same singleton to get their location info.