Core Location usage change recently, but even after updating to the new specification I can't seem to get it working.
I tried starting a new project with just a view controller that changes its background color upon GPS coordinate finding or failure.
#import "ViewController.h"
#interface ViewController (){
CLLocationManager *locationManager;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
if (locationManager == nil)
{
locationManager = [[CLLocationManager alloc] init];
}
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if (![CLLocationManager locationServicesEnabled]) {
[self.view setBackgroundColor:[UIColor redColor]];
}
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[locationManager requestAlwaysAuthorization];
[locationManager startUpdatingLocation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark CLLocationManagerDelegate
//
//
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
{
[self.view setBackgroundColor:[UIColor greenColor]];
NSLog(#"lat:%f lon:%f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
//Debug(#"did fail with error. stop updating and return error.");
[self.view setBackgroundColor:[UIColor orangeColor]];
}
#end
I added
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs your location to provide the best service.</string>
to the Info.plist file, and still... no changes, the location icon appears on the status bar near the battery but no location ever comes, real or simulated.
Am I missing something?
Try adding the change authorisation method:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
// This method has to be here to trigger the UIAlertView
switch (status) {
case kCLAuthorizationStatusDenied:
break;
case kCLAuthorizationStatusRestricted:
break;
case kCLAuthorizationStatusNotDetermined: {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[self.locationManager requestAlwaysAuthorization];
}
default:
break;
}
}
EDIT
You're using the wrong delegate method. didUpdateToLocation has been deprecated. Use this instead:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {}
Related
I am a new in ios programming. I'm having problems trying to show a map showing a pin with the current user position.
#implementation ViewController
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];
if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways ||
authorizationStatus == kCLAuthorizationStatusAuthorizedAlways ||
authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self.locationManager startUpdatingLocation];
mapView.showsUserLocation = YES;
[self.mapView delegate];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
info.plist has NSLocationWhenIsUseUsageDescription property, but it is not displaying the pin nor making zoom to the user location.
Try this code instead, you are asking it to start updating location inside the if block which doesn't seem right to me.
And also I am not sure what you are trying to do with this line inside the if block.
Apart from this there can be multiple issues in your approach.. I would advise you to look at a good tutorial for this.
[self.mapView delegate];
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];
if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways ||
authorizationStatus == kCLAuthorizationStatusAuthorizedAlways ||
authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse) {
mapView.showsUserLocation = YES;
[self.mapView delegate];
}
You might want to look into the didUpdateUserLocation method. After you ask for a map to display the User Location, it can take some time for a response. The didUpdateUserLocation method is accessed when the system gets back to you with data about the User Location. didUpdateUserLocation is the place where you'd put your code to do whatever you want to do with the map now that you have the user location.
This seems like very basic question but I didnt find anything, and I have tried all!! I just want to make a button to zoom in into users location! This is what I've got so far:
CLLocationCoordinate2D userLocationCoordinate;
- (void)viewDidLoad {
[super viewDidLoad];
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){
[self.locationmanager requestWhenInUseAuthorization];}
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"OldLocation %f %f", oldLocation.coordinate.latitude, oldLocation.coordinate.longitude);
NSLog(#"NewLocation %f %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
userLocationCoordinate.latitude = newLocation.coordinate.latitude;
userLocationCoordinate.longitude = newLocation.coordinate.longitude;
}
-(IBAction)showUserLocation:(id)sender{
[self.mapview setCenterCoordinate:userLocationCoordinate animated:YES];
}
Please I need help, If theres a way in which I dont use CLLocationManager it would be better.
Thanks.
You still need CLLocationManager to request location permission from the user,
but you can use the setUserTrackingMode method of MKMapView to ask the map view to centre on the user's location.
If you don't want to continue to update the map location as the user moves then you should set the tracking mode to Follow and then set it to None after a few seconds.
Getting the user location to work has been killing me...
I've read lots of threads explaining the new changes with iOS 8 and how there must be one of two keys (NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription) in the info.plist file in order for the app to ask permission to get user location. I did that.
I've also included what I believe as all the code needed for the location service to work...but it doesn't. Please see my mapViewController.h and mapViewController.m files below:
mapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
#interface mapViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property(nonatomic, retain) IBOutlet MKMapView *mapView;
#property(nonatomic, retain) CLLocationManager *locationManager;
#end
mapViewController.m
#import "mapViewController.h"
#interface mapViewController ()
#end
#implementation mapViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.mapView.delegate = self;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER) {
// Use one or the other, not both. Depending on what you put in info.plist
//[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
#endif
[self.locationManager startUpdatingLocation];
self.mapView.showsUserLocation = YES;
[self.mapView setMapType:MKMapTypeStandard];
[self.mapView setZoomEnabled:YES];
[self.mapView setScrollEnabled:YES];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
self.locationManager.distanceFilter = kCLDistanceFilterNone; //Whenever we move
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
NSLog(#"%#", [self deviceLocation]);
//View Area
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.longitudeDelta = 0.005f;
region.span.longitudeDelta = 0.005f;
[self.mapView setRegion:region animated:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
- (NSString *)deviceLocation {
return [NSString stringWithFormat:#"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceLat {
return [NSString stringWithFormat:#"%f", self.locationManager.location.coordinate.latitude];
}
- (NSString *)deviceLon {
return [NSString stringWithFormat:#"%f", self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceAlt {
return [NSString stringWithFormat:#"%f", self.locationManager.location.altitude];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Also, in case this is relevant, the mapViewController is tied to a tab in a Tab View Controller. When I click on the tab that includes the view controller containing MKMapView, I get the below image:
Use this code and run the application in device to get the current location.
If you run in simulator, then it will show the default location i.e Apple Inc's address as current location.
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self ];
self.mapView.showsUserLocation=YES;
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[self.mapView setCenterCoordinate:newLocation.coordinate animated:YES];
MKCoordinateRegion region=MKCoordinateRegionMakeWithDistance(newLocation.coordinate,70000 ,70000 );
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:region];
[self.mapView setRegion:adjustedRegion animated:YES];
}
Note:
Turn on data or wifi in your device, or else you will face Location Accuracy error.
Add the below code to your ViewController.h class,
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#property(nonatomic, retain) CLLocationManager *locationManager;
#end
And in ViewController.m class ,
-(void)viewWillAppear:(BOOL)animated{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
[super viewWillAppear:animated];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D zoomLocation = CLLocationCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude);
}
Per the docs, [self.locationManager requestAlwaysAuthorization] is asynchronous. Implement the location services auth changed delegate callback and start monitoring there only after the auth status is allowed.
I am building an iOS application that display a POI in a MapView, but firstly I can display the map, and with iOS8 this is begin a problem.
I read a lot question in this site, but none run on my app even if the code seems right.
I entered into myapplicationTest-info.plist the following code
<key>NSLocationAlwaysUsageDescription</key>
And the code in the file.m is this:
#import "MapViewController.h"
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize mapView = _mapView ;
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
self.locationManager.delegate = self;
self.locationManager = [[CLLocationManager alloc] init];
if (IS_OS_8_OR_LATER) {
//[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
self.mapView.showsUserLocation = YES;
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
self.locationManager.distanceFilter = kCLDistanceFilterNone; //Whenever we move
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
NSLog(#"%#", [self deviceLocation]);
//View Area
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.longitudeDelta = 0.005f;
region.span.longitudeDelta = 0.005f;
[mapView setRegion:region animated:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
- (NSString *)deviceLocation {
return [NSString stringWithFormat:#"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceLat {
return [NSString stringWithFormat:#"%f", self.locationManager.location.coordinate.latitude];
}
- (NSString *)deviceLon {
return [NSString stringWithFormat:#"%f", self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceAlt {
return [NSString stringWithFormat:#"%f", self.locationManager.location.altitude];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Where is the mistake?
Why it doesn't run?
You need to provide a value for NSLocationAlwaysUsageDescription key which is the string that describes why your app wants to use location services -
For example -
<key>NSLocationAlwaysUsageDescription</key>
<string>FindMeDonuts will use your location to identify nearby donut shops</string>
Also, rather than checking the iOS version, it is better to check if CLLocationManager responds to the authorisation selector -
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
finally, this won't stop your map from updating, but it doesn't make sense - you are assigning a delegate to your CLLocationManager before you allocate and initialise it.
You should say -
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate=self;
I don't know if i understand your problem.
if your problem is about the map is not show, you need to set frame of your map.
self.mapView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
hope i could help you
The best way is to use the -locationManager:didUpdateLocations method provided by CLLocationManagerDelegate.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
[self.locationManager stopUpdatingLocation];
// Move this line here
self.mapView.showsUserLocation = YES;
}
After calling [self.locationManager startUpdatingLocation] in ViewDidLoad, you shouldn't set self.mapView.showsUserLocation to YES yet as permission to use location services is not yet approved. Use the delegate to wait/get a location update from the system before setting self.mapView.showsUserLocation to YES.
You also need to enable location services
if([CLLocationManager resolveClassMethod:#selector(locationServicesEnabled)]) {
[CLLocationManager locationServicesEnabled];
}
I am trying to get the Map Kit to display the current user's location down to a predefined size.
Everything was working but since updating to Xcode 6 and iOS 8, things have changed.
I have implemented the necessary authorizations and now the app crashes. The code with *** is the code that the system seems to have a problem with.
Here is Map.m
#import "MRVCMapViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import CoreLocation;
#interface MRVCMapViewController ()
#end
#implementation MRVCMapViewController
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
//location permission
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
//mapview settings
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
***MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];***
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You haven't checked that the userLocation value is valid. You should make sure it is not nil before trying to use it for anything.