I am creating a simple UIMapView with custom annotations. Just upgraded to Yosemite and Xcode 6.1.1. I have tried everything to get user location to show on map but for some reason the blue dot doesn't show on the map. I have selected show user location in the inspector for the UIMapView. The error listed at the end shows in the log window at the bottom of the screen when I run it on my phone. Thank you for any help.
My .h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
My .m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.mapView.delegate self];
[self.mapView setShowsUserLocation:YES];
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
CLLocationCoordinate2D loc = [userLocation coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 500, 500);
[self.mapView setRegion:region animated:YES];
}
ERROR RECEIVED AFTER RUNNING
501:107687] Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
As per my comments on the question... you are in a Permission error situation.
You need t check for User Permission before you call the update methods...
CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];
if (authorizationStatus == kCLAuthorizationStatusAuthorized ||
authorizationStatus == kCLAuthorizationStatusAuthorizedAlways ||
authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse) {
// update location here...
}
Then, as pointed out by #zaheer, you need to add a Key-Value par to the -Info.plist
NSLocationWhenInUseUsageDescription
Some Message To The User About Why You Want Their Location
or
NSLocationAlwaysUsageDescription
Some Witty Comment About The NSA
depending upon whether you need the location only when the app is in the foreground, or in the background...
Related
I create a sample project to get user location.
But When I run the app, the location permission not show to me.
What's wrong with my code?
Thanks.
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *latLabel;
#property (weak, nonatomic) IBOutlet UILabel *longLabel;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager.delegate = self;
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
CLLocation *currentLocation = [locations lastObject];
if(currentLocation != nil){
self.latLabel.text = [NSString stringWithFormat:#"%.2f",currentLocation.coordinate.latitude];
self.longLabel.text = [NSString stringWithFormat:#"%.2f",currentLocation.coordinate.longitude];
[self.locationManager stopUpdatingLocation];
}
}
#end
You need to start by checking locationServicesEnabled. If they are enabled, preceed to call authorizationStatus to learn your app's actual authorization status. You ask for the authorization dialog only if the status is "not determined".
If the status is anything else, there is no point asking for the authorization dialog; it won't appear.
Another problem is that this code is useless:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
CLLocation *currentLocation = [locations lastObject];
if(currentLocation != nil){
self.latLabel.text = [NSString stringWithFormat:#"%.2f",currentLocation.coordinate.latitude];
self.longLabel.text = [NSString stringWithFormat:#"%.2f",currentLocation.coordinate.longitude];
[self.locationManager stopUpdatingLocation];
}
}
You are calling stopUpdatingLocation as soon as you get your first location update. But the chances of your getting a useful location on the first location update are basically nil, because the sensors are just warming up.
(Also please note that it is pointless to check "Location updates" in your background modes. You will not get any location updates in the background unless you set the location manager's allowsBackgroundLocationUpdates to YES, and you are not doing that.)
I want to show the user's current location on map using MapKit and everything goes ok but the user current location is not visible on the maps.
Here are the properties I have set for mapView:
Here is rest of the controller's code:
#import <MapKit/MapKit.h>
#import "ShowMarkerAndNavigateVC.h"
#interface ShowMarkerAndNavigateVC ()
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#end
CLLocationManager *mgr;
#implementation ShowMarkerAndNavigateVC
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"View loaded Successfully");
mgr = [[CLLocationManager alloc] init];
[mgr requestWhenInUseAuthorization];
NSLog(#"Reuquested always authorization");
}
- (IBAction)backButtonPressed:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
#end
I have also set the mapView delegate to the current controller as shown here:
The expected result is that it should show the user's current location.
The actual result is that it does not show location on the map as shown here:
First, I would suggest actually setting showsUserLocation property to YES in code.
Second, note that it is up to you to show the region where the user location actually is; for example:
- (void)mapView:(MKMapView *)mapView
didUpdateUserLocation:(MKUserLocation *)userLocation {
CLLocationCoordinate2D coordinate = userLocation.location.coordinate;
MKCoordinateRegion reg =
MKCoordinateRegionMakeWithDistance(coordinate, 600, 600);
mapView.region = reg;
}
If you're using the simulator, you won't get the user's location, because the simulator doesn’t know its own location.
To do so, open the Debug menu of the Simulator and select Apple in the ***Location* sub-menu.
Hope this will help you.
what i need for my app is, to display my current location on my mapview by using location service,
here is my code
.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapDirectoryViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *myMapView;
- (IBAction)backAction:(id)sender;
#end
.m
#interface MapDirectoryViewController ()
#end
#implementation MapDirectoryViewController
{
MKCoordinateRegion myRegion;
CLLocationCoordinate2D center;
MKCoordinateSpan span;
NSMutableArray *locations;
CLLocationCoordinate2D location;
Annotation *myAnnoation;
}
#synthesize myMapView;
- (void)viewDidLoad {
[super viewDidLoad];
myMapView.showsUserLocation = YES;
[myMapView setShowsUserLocation:YES];
[myMapView setCenterCoordinate:myMapView.userLocation.location.coordinate animated:YES];
}
#delegation
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
//what do i need to do in here?
}
what i need excatly is to get blue dot to show up on map and make the dot as center of the map when app loads,
as you can see in my viewdidload, i tried many way to active the user current location, but none of them works...
and i realise one more thing in my actual iphone6, under general, my app doesnt have 'location' option there so i cant phycially go to active it.... e.g google map or facebook app they all have 'location' option under general app config...
any advise? any code example would be really helpful, thank you very much.
If you set location permission i.e.
[LocationManager requestWhenInUseAuthorization]
or
[LocationManager requestAlwaysAuthorization]
then set
[self.mapLocation setShowsUserLocation:YES];
and also write code in map annotation delegate like this:
- (MKAnnotationView *)mapView:(MKMapView *)mapViewIn viewForAnnotation:(id <MKAnnotation>)annotation {
//Your stuff
if (annotation == _mapLocation.userLocation) {
return nil;
}
}
solution:
1, edit the source code of the Info.Plist with Right click > open as > Source code and add these lines:
<!-- for requestAlwaysAuthorization -->
<key>NSLocationAlwaysUsageDescription</key>
<string>Explain for what are you using the user location</string>
<!-- for requestWhenInUseAuthorization -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Explain for what are you using the user location</string>
2,
- (void)viewDidLoad {
[super viewDidLoad];
serviceConnector = [[ServiceConnector alloc] init];
serviceConnector.delegate = self;
[serviceConnector retrieveDataFromWebservice:ALL_MOSQUE_ADDRESS_JSON_WS];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
[myMapView setShowsUserLocation:YES];
[myMapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
[myMapView setCenterCoordinate:myMapView.userLocation.location.coordinate animated:YES];
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
NSLog(#"location delegate called");
}
now it get me the current location with blue dot , and calling deleagation method correctly in ios 8
I've updated to Xcode 6 (from Xcode 5) and now my app is not working anymore (I was quite proud it worked under IOS7). I have this "famous" debug output:
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
Of course I've been googling this message to find a solution but it seems that nothing's working. So I am asking for your advice.
Here is my header file:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "MapPoint.h"
#define kGOOGLE_API_KEY #"my google api"
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#interface XYZViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
CLLocationCoordinate2D currentCentre;
int currenDist;
BOOL firstLaunch;
}
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#end
And here is my implementation file:
#import "XYZViewController.h"
#import "DetailViewController.h"
#interface XYZViewController ()
#end
#implementation XYZViewController
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Make this controller the delegate for the map view.
self.mapView.delegate = self;
// Ensure that you can view your own location in the map view.
[self.mapView setShowsUserLocation:YES];
//Instantiate a location object.
locationManager = [[CLLocationManager alloc] init];
//Make this controller the delegate for the location manager.
[locationManager setDelegate:self];
//Set some parameters for the location object.
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
firstLaunch=YES;
}
You need to do as the error description tell you, and add a call to requestWhenInUseAuthorization or requestAlwaysAuthorization. This has been covered before, ie. iOS alertview for location permission doesn't pop up
The required changes could look like this:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Make this controller the delegate for the map view.
self.mapView.delegate = self;
//Instantiate a location object.
locationManager = [[CLLocationManager alloc] init];
//Make this controller the delegate for the location manager.
[locationManager setDelegate:self];
//Set some parameters for the location object.
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
// Request use on iOS 8
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
// Ensure that you can view your own location in the map view.
[self.mapView setShowsUserLocation:YES];
} else {
[locationManager requestWhenInUseAuthorization];
}
firstLaunch=YES;
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
// Ensure that you can view your own location in the map view.
[self.mapView setShowsUserLocation:YES];
}
}
The above code do a version check (in the apple recommended way), you could also do a feature check, which is cleaner, but sometime cause problems in my own experience.
The tricky part is you need to provide a description of your use in the app Info.plist. Else the UIAlert will not appear and you will not be given permission. Go to the project/target settings in xcode, click the "Info" tab. Click the + button. For the key enter NSLocationWhenInUseUsageDescription and the value should be a string describing how you will use the user's location. You can also open the 'Info.plist' file under 'Supporting Files'.
I suspect this is why it hasn't worked for you yet.
I have written a simple method to utilize MKMapViewDelegate and I am having some trouble displaying the user location in the xcode 5 simulator. My understanding is that the code should be executed after a button from a previous view controller is pressed and the corresponding UIViewController class is created. However when the button is pressed and the View Controller with said map view is pushed onto the stack it simply displays the map with no zoom and no location. If I run the same code as a single view stand alone app it works just fine. What must I add or change to get the map to zoom to the users current location (in simulator its the San Fran headquarters) Here is the code I am using;
header:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface SPMenuViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *myMapView;
#end
implementation:
#import "SPMenuViewController.h"
#interface SPMenuViewController ()
#end
#implementation SPMenuViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.myMapView.delegate = self;
[self.myMapView setShowsUserLocation:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// Coords
CLLocationCoordinate2D myLocation = [userLocation coordinate];
// Zoom Region
MKCoordinateRegion zoomRegion = MKCoordinateRegionMakeWithDistance(myLocation, 2500, 2500);
// Show Location
[self.myMapView setRegion:zoomRegion animated:YES];
}
I think it should be noted that the previous view is Embedded in a Navigation Controller and a UIButton Class is connected by "push" segue to the View Controller containing the map view. Please help thank you!
If you set a breakpoint, is the userLocation value valid?
Setting showsUserLocation:YES should handle getting/displaying userLocation for you, but doesn't guarantee that the location will be on the map. Since you're setting the user location and zoomRegion in a delegate method, check when/if that method is actually called before the view appears. Could be it doesn't have an initial value to work with.
You could try setting the initial userLocation and zoomRegion in viewDidLoad instead of in didUpdateLocation to see if that works any better. This all looks like it should work ok.
Maybe a missing XCode setting to simulate location?
Current Location in the Simulator