I want to get the latitude and longitude of the user and display it on the Apple Watch.
I have already included the core location framework in my Watchkit Extension.
When I run the program all I get for the lat and long is 0.0 and 0.0
I tested the same method in a class on the iPhone and it worked, and gave me the appropriate coordinates. What am I doing wrong?
The .h file:
#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface InterfaceController : WKInterfaceController
#end
The .m file:
#import "InterfaceController.h"
#interface InterfaceController()
#end
#implementation InterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
}
- (void)willActivate {
// This method is called when watch view controller is about to be visible to user
[super willActivate];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
[super didDeactivate];
}
- (IBAction)showLocation {
NSString * geoLoc = [NSString stringWithFormat:#"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
NSLog(geoLoc);
}
#end
Before you can get any location updates to your watch app extension you will need to authorize location updates in your iPhone app. If you haven't authorized location updates in your iPhone app, then your watch extension will not get any location updates. Also, I am pretty sure you need to set the permission to always allow for location updates [CLLocationManager requestAlwaysAuthorization]. I don't think it will work if you use [CLLocationManager requestWhenInUseAuthorization], though I am not 100% sure about the permissions.
In Xcode, you want use the Debug menu to simulate a location that's either pre-set or use a GPX file as the location source.
In the CLLocationMananager documentation, the location property states
The value of this property is nil if no location data has ever been retrieved.
That means that you need to call [self.locationManager startUpdatingLocation] in order to get a valid location. But there a could things you need to do before that will work.
First of all you will need to request authorization by calling [self.locationManager requestAlwaysAuthorization].
When authorization is approved or declined, the delegate method locationManager:didChangeAuthorizationStatus: will be called.
If the authorization status is kCLAuthorizationStatusAuthorizedAlways than you can call [self.locationManager startUpdatingLocation].
Then anytime the location is updated, the delegate method
locationManager:didUpdateLocations: will be called so you can update your UI with the new location.
You are not supposed to request location data within a WatchKit Extension.
From Apple Watch Human Interface Guidelines:
“Avoid using technologies that request user permission, like Core
Location. Using the technology from your WatchKit extension could
involve displaying an unexpected prompt on the user’s iPhone the first
time you make the request. Worse, it could happen at a time when the
iPhone is in the user’s pocket and not visible.”
I am using this code
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8)
{
[locationManager requestAlwaysAuthorization];
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
and to display in wkinterfaceMap i use this code
CLLocationCoordinate2D mapLocation = CLLocationCoordinate2DMake([latitude floatValue],[longitude floatValue]);
//
MKCoordinateSpan coordinateSpan = MKCoordinateSpanMake(1, 1);
[self.mapkit addAnnotation:mapLocation withPinColor: WKInterfaceMapPinColorPurple];
[self.mapkit setRegion:(MKCoordinateRegionMake(mapLocation, coordinateSpan))];
Related
After submitting my App I need to get user location with CoreLocation (#import ) but it NEVER ask me the permission alert.
ViewController.h
#import "RootViewController.h"
#import < UIKit/UIKit.h >
#import < CoreLocation/CoreLocation.h >
#interface AroundMeViewController : RootViewController <CLLocationManagerDelegate>
#property(nonatomic, strong) CLLocationManager *locationManager;
...
#end
__________
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"LOG: %d", [CLLocationManager locationServicesEnabled]);
self.locationManager = [[CLLocationManager alloc] init];
// Set a delegate to receive location callbacks
self.locationManager.delegate = self;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
....
// Start the location manager
[self.locationManager startUpdatingLocation];
NSLog(#"LOG: %#", self.locationManager);
.....
}
I really tried in so many way to solve this issue (different devices, allow manually from privacy settings) but I don't know where is my mistake.
According to NSHipster, permission to use location services must be asked explicitly, and is given asynchronously, so we can't immediately start location updates like we used to. We need to implement the
locationManager:didChangeAuthorizationStatus
delegate method and start location updates there. This method is called any time the auth status changes based on user input.
It seems this delegate method is also called when locationManager is set up, as mine was triggering while splash screen was still showing (when I set locationManager delegate, I suspect), and then again when I called triggerLocationServices(). This could be what is in effect "silencing" your request.
I changed my methods to the following:
func triggerLocationServices() {
if CLLocationManager.locationServicesEnabled() {
if self.locationManager.respondsToSelector("requestAlwaysAuthorization") {
// request authorization to use location
} else {
// start updating location
}
}
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus){
if status == .AuthorizedAlways || status == .AuthorizedWhenInUse {
// start updating location
}
else {
triggerLocationServices()
}
}
and removed any other calls to triggerLocationServices(). This, along with the correct info.plist keys, resolved it for me.
Apologies for Swift code, hope you can translate into Obj-C.
I'm trying to getting my current location exact according to my coordinates. I've implemented CLLocationManager in my viewController called myLocation.
My problem is, I'm getting not getting my co-ordinates for the first time, but when I again approach I got the coordinates. I'm unable to understand this problem that why this not appear for the first time.
I also tried to give a NSTimer to stoplocation but but still unable to get the result for the first time, every first time I getting a (null) value, and then getting the co-ordinates.
My Code:
#import <UIKit/UIKit.h>
#import <Corelocation/CoreLocation.h>
#interface myLocation : UITableViewController<CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#interface myLocation () {
CLLocationManager* _locationManager;
NSString * _lat;
NSString * _lng;
}
#end
#implementation myLocation
- (void)viewDidLoad
{
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[_locationManager requestWhenInUseAuthorization];
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
[_locationManager stopUpdatingLocation];
_lat =[NSString stringWithFormat:#"%f",location.coordinate.latitude];
_lng =[NSString stringWithFormat:#"%f",location.coordinate.longitude];
}
- (void)viewWillAppear:(BOOL) animated
{
NSLOG(#"%#",_lat);
NSLOG(#"%#",_lng);
}
Your coordinates aren't appearing yet when you attempt to print them in viewWillAppear: because the CLLocationManager hasn't had enough time to retrieve the first location yet. Wait until didUpdateLocations: is first called before attempting to utilize the device coordinates because didUpdateLocations: is where you'll be receiving those coordinates. I recommend deleting your attempt to print the coordinates code from your viewWillAppear and simply print them in didUpdateLocations: instead.
In the comments, the OP stated he wants to "refresh" the location during viewWillAppear. I suggest stopping the updates when the view disappears and restarting the updates as soon as the view reappears:
- (void)viewWillAppear:(BOOL) animated
{
[_locationManager startUpdatingLocation];
}
- (void)viewWillDisappear:(BOOL) animated
{
[_locationManager stopUpdatingLocation];
}
It takes some time for location services to start up and call your delegate method - This almost certainly won't happen before viewWillAppear is called if you are only starting location services in viewDidLoad. Also, the first time your app executes it has to wait for the user to grant permission.
You can examine the location property of your CLLocationManager to get the most recent location. If it is nil then no location has been determined (yet).
I have been trying to move my iOS7 app with MKMapview to support iOS8. However I couldn't get the new request for users to share their locations to work properly. I create my MKMapView on a storyboard and the delegate is set and works perfectly on iOS7. Here is what I've added to support iOS8 Location sharing:
myMapView.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface myMapView : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) CLLocationManager *locationManager;
myMapView.m
//Code omitted
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
//Code omitted
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if(IS_OS_8_OR_LATER) {
//[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
}
[self.mapView setShowsUserLocation:YES];
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
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.latitudeDelta = 0.0187f;
region.span.longitudeDelta = 0.0137f;
[self.mapView setRegion:region animated:YES];
_initialPosition = NO;
}
Also I have set NSLocationAlwaysUsageDescription key and its value in my InfoPlist, which shows the correct message when prompting the user to share their location.
Unfortunately the delegate function -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations never gets called. Although each time the viewController gets loaded the [self.locationManager startUpdatingLocation] is called, but the delegate does not seem to respond to it. Is there a problem of how I set the delegate or is there something else I am missing here?
UPDATE: It seems also that my gpx file is not being called on launch. I have cleared and reloaded my location file, even changed to a default location, but no location is found: Domain=kCLErrorDomain Code=0
UPDATE 2: Here is a SS from the settings that I have actually succeeded with the user request, but fail to get/update location no matter how much I refresh.
(source: barisaltop.com)
Thanks!
I had the same problem a few days ago. The solution was adding the string keys NSLocationAlwaysUsageDescription (for [CLLocationManager requestAlwaysAuthorization]) or NSLocationWhenInUseUsageDescription (for [CLLocationManager requestWhenInUseAuthorization]) to your Supporting Files/Info.plist
You can also 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>
Hope this helps.
Finally I have succeeded to run my gpx file on the simulator. It seems that after installing Xcode 6 the first time, there might be a bug causing for gpx files to simulate. Here is how I overcame the problem:
I have deleted my app from the simulator
Under App->Capabilities enabled Background Modes->Location updates
Run the app and let it install on simulator
Allow access, and I was able to locate the user with GPX
Afterwards I disabled Location Updates.
I don't know why, but this did the trick for me.
I installed XCODE 6 the version form developer.apple (I think is the final one) and Im working my projects there (iOS 7 projects) but obviously brings iOS 8 SDK I really don't know if this affects the project.
I have a mapview and I want to show the user location but it's impossible!
Code:
#property (nonatomic, strong) CLLocationManager *manager;
- (void)viewDidLoad {
[super viewDidLoad];
[self.manager requestAlwaysAuthorization];
[self.manager requestWhenInUseAuthorization];
[self.mapview setDelegate:self];
self.mapview.showsUserLocation = YES;
[self.mapview setCenterCoordinate:self.mapview.userLocation.location.coordinate animated:YES];
}
I don't get the "App whants to use your current location...", The mapview shows some place in Africa without pin or anything.
You must init/alloc the CLLocationManager *manager
something like this:
// Create the core location manager object
_locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// for iOS 8, specific user level permission is required,
// "when-in-use" authorization grants access to the user's location
//
// important: be sure to include NSLocationWhenInUseUsageDescription along with its
// explanation string in your Info.plist or startUpdatingLocation will not work.
//
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
check Apple example https://developer.apple.com/library/prerelease/ios/samplecode/LocateMe/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007801
How can I get the user Location in a simple ViewController in iOS 7?
I have tried in this way, but on debugging I saw that didUpdateLocation method isn't called:
In MyViewController.h:
#import <CoreLocation/CoreLocation.h>
#interface MyViewController : UIViewController <CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
In MyViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
//locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
CLLocation *newLocation = [locations lastObject];
NSLog(#"NewLocation %f %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"Failed %ld",(long)[error code]);
}
didUpdateLocations isn't called, but is called didFailWithError printing in log: "Failed 0". Please help me!
Firstly check that you actually have a valid WiFi and 3G connection
then
1) go to settings and reset your location services
2) reset your network settings
Also check is the default location set if its in a simulator. This link will show that.
CLLocation manager says
kCLAuthorizationStatusNotDetermined = 0, // User has not yet made a choice with regards to this application
kCLAuthorizationStatusRestricted, // This application is not authorized to use location services. Due
// to active restrictions on location services, the user cannot change
// this status, and may not have personally denied authorization
kCLAuthorizationStatusDenied, // User has explicitly denied authorization for this application, or
// location services are disabled in Settings
kCLAuthorizationStatusAuthorized // User has authorized this application to use location services
In your case CLAuthorizationStatus 0 means you not allow app to access location services.