-[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] error - iphone

This is my code, showing both the alert and the blue dot for the current position on the map:
MapName.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface MapName : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *MapName;
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
MapName.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
//Center the map
[self gotoLocation];
//Show current position
_MapName.showsUserLocation = YES;
}
I've added the key NSLocationWhenIsUseUsageDescription as a string to the Info.plist.
I'm still getting the same error on Xcode.

It is due to both:
[self.locationManager startUpdatingLocation];
and
_MapName.showsUserLocation = YES;
You need to check if the user has given permission before you call these. Also make sure you turn off User Location in the MKMapKit on the storyboard (this one took me days to track down).
Do something like:
CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];
if (authorizationStatus == kCLAuthorizationStatusAuthorized ||
authorizationStatus == kCLAuthorizationStatusAuthorizedAlways ||
authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self.locationManager startUpdatingLocation];
_MapName.showsUserLocation = YES;
}
Depending on your app you may not want to ask for the user's permission on launch since that is not recommended.

The error message is pretty literal. Don't call [self.locationManager startUpdatingLocation] until you have authorization. Your [self.locationManager requestWhenInUseAuthorization], per the docs, is asynchronous.
When the current authorization status is kCLAuthorizationStatusNotDetermined, this method runs asynchronously and prompts the user to grant permission to the app to use location services.
This means you are both prompting for access as well as starting your scan at the same time.
Instead, try implementing -[CLLocationManagerDelegate locationManager:didChangeAuthorizationStatus:] and starting your scan there after it's been determined that you have authorization.

On swift :
let locationManager: CLLocationManager = CLLocationManager()
let authorizationStatus = CLLocationManager.authorizationStatus()
override func viewDidLoad() {
super.viewDidLoad()
if(authorizationStatus == .AuthorizedWhenInUse || authorizationStatus == .AuthorizedAlways) {
locationManager.startUpdatingLocation()
}
else
{
locationManager.requestWhenInUseAuthorization()
}
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
}
Don't forget to add into Info.plist file these keys:

The keyword in the info file is ("In" instead of "Is"):
NSLocationWhenInUseUsageDescription

This way is working without errors on Xcode6:
AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) UIWindow *window;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize locationManager = _locationManager;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Current position
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager requestWhenInUseAuthorization];
return YES;
}
#end
The alert message shows when you open the app for the first time

Based off of Jerome's response, I translated the answer that worked for me to Swift.
let authorizationStatus = CLLocationManager.authorizationStatus()
if(authorizationStatus == .AuthorizedWhenInUse || authorizationStatus == .AuthorizedAlways) {
self.findMyLocation()
}
Note: From what I read in the documents, there is no kCLAuthorizationStatusAuthorized equivalent in Swift.

Related

Why can't I read the device's deviation from the magnetic North with this code?

OK the code is now working, but it still needs work. The values I get are "sticky", they are not stable (the magnetic North seems to move a bit every time I try to return to it), and I need to shake the device a bit in order to refresh/wake-up the values..
Game.h
#import <Foundation/Foundation.h>
#import "CoreLocation.h"
#interface Game : NSObject
<CLLocationManagerDelegate>
#property BOOL stopButtonPressed;
-(void) play;
#end
Game.m
#implementation Game
- (id) init
{
self = [super init];
self.stopButtonPressed = NO;
CLLocationManager *locationManager;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
return self;
}
-(void) play
{
[locationManager startUpdatingHeading];
while(!self.stopButtonPressed)
{
double degrees = locationManager.heading.magneticHeading;
int degreesRounded = (int)degrees;
NSLog(#"Degrees : %i", degreesRounded);
}
}
#end
MyViewController.m
#interface MyViewController()
{
Game *game;
}
#end
#implementation MyViewController
-(void) viewDidLoad
{
game = [[Game alloc] init];
}
- (IBAction)playPressed:(UIButton *)sender
{
[game performSelectorInBackground:#selector(play) withObject:nil];
}
- (IBAction)stopPressed:(UIButton *)sender
{
game.stopButtonPressed = YES;
}
#end
What am I doing wrong?
This code will block the thread, and if it's happening in the main thread, you will never get the button press.
CLLocationManager is an asynchronous mechanism. To work with it properly, you must provide a delegate which it will notify when updates to location are available (this can be self in most cases (where self is a viewController or similar). See CLLocationManagerDelegate docs
...
CLLocationManager *locationManager;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingHeading];
}
- (void)locationManager:manager didUpdateHeading:newHeading {
double degrees = newHeading.magneticHeading;
NSLog(#"Degrees : %F", degrees);
}
You should catch the CLLocationManager delegate methods instead of calling the properties directly: https://developer.apple.com/library/mac/#documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html#//apple_ref/occ/intf/CLLocationManagerDelegate

How can I integrate core location data to my blank iPhone App without introducing View or tab controller?

How can I integrate core location data (Lat, Long, Altitude) into my (single view) iPhone app without creating additional view controllers or tab controllers? in other words, when I run the app I want to see a blank screen (xView) but be able to collect (Longitude, Latitude information in the background and then maybe store the coordinates in a file or pass it on to a other functions. Sorry if this sounds like a dumb question. I am new to iOS development. Thanks.
HelloXYZAppDelegate.h:
#import <UIKit/UIkit.h>
#import "MyclassView.h"
#interface HelloXYZAppDelegate: NSObject <UIApplicationDelegate>
{
MyClassView* _xView;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MyClassView *xView;
#end
HelloXYZAppDelegate.m
#import "HelloXYZAppDelegate.h"
#implementation HelloXYZAppDelegate
#synthesize xView=_xView;
#synthesize window=_window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
{
self.xView = [[[MyClassView alloc] initWithFrame:screenBounds] autorelease];
[self.window addSubview:_xView];
[self.window makeKeyAndVisible];
return YES;
}
#end
MyClassView.h:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#include <OpenGLES/ES2/gl.h>
#interface MyClassView : UIView
{
CAEAGLLayer* _eaglLayer;
EAGLContext* _context;
GLuint _CRBuffer;
GLuint _PSlot;
....
....
....
CLLocationManager *LM; //not sure if I can do this in here
CLLocation *SP; //not sure if I can do this in here
}
#property (nonatomic, retain) CLLocationManager *LM;
#property (nonatomic, retain) CLLocation *SP;
#end
MyClassView.m
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (SP == nil)
self.SP = newLocation;
NSString *latitudeString = [[NSString alloc] initWithFormat:#"%g\u00B0",
newLocation.coordinate.latitude];
NSLog(#"latitude is %#", latitudeString);
[latitudeString release];
}
- (void)viewDidLoad
{
self.LM = [[CLLocationManager alloc] init];
LM.delegate = self;
LM.desiredAccuracy = kCLLocationAccuracyBest;
[LM startUpdatingLocation];
[super viewDidLoad];
}
very simple tutorial on core location. If you're looking to store the data for use later on you'll either want to make a data NSObject class, but seeing as you dont want to make extra classed, define two #property NSStrings lat and long, when the location is created set the two strings to the two variables and you can access them later.
The tutorial prints the data on the screen, just leave that part out if you dont want it

Warning from AppDelegate

I am getting the following warning when I am calling other view controllers..
WindowMultivewAppDelegate might not respond to -switchView to view
This is my code in the Firstviewcontroller.m
- (IBAction)swapViews:(id)sender{
WindowMultiViewAppDelegate *delegate = (WindowMultiViewAppDelegate *)[[UIApplication sharedApplication] delegate];
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[delegate switchView:self toView:secondView.view];
}
this is my code in the Firstviewcontroller.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
}
- (IBAction)swapViews:(id)sender;
#end
in the appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
initWithNibName:#"FirstViewController" bundle:nil];
[self.window addSubview:navigationController.view];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
if ([CLLocationManager locationServicesEnabled]) {
[locationManager startUpdatingLocation];
}
[self.window makeKeyAndVisible];
return YES;
}
in the appdelegate.h
#interface WindowMultiViewAppDelegate : NSObject <UIApplicationDelegate, CLLocationManagerDelegate , MKMapViewDelegate> {
UIWindow *window;
UINavigationController *navigationController;
CLLocationManager *locationManager;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet CLLocationManager *locationManager;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
I have placed a UInavgationcontroller into the mainWindow.xib which leads to the rootviewcontroller which i named FirstViewController
The application quites in the secondviewcontroller when a button next is pressed which has that action inside
- (IBAction)swapNext:(id)sender
{
WindowMultiViewAppDelegate *delegate = (WindowMultiViewAppDelegate *)[[UIApplication sharedApplication] delegate];
MediaViewController *mediaView = [[MediaViewController alloc] initWithNibName:#"MediaViewController" bundle:nil];
[delegate switchView:self toView:mediaView.view];
}
What am I doing wrong??
Can anybody tell me how to connect more subviews into the UINavigationController
I want one of this subviews to be a video player - offline- and the other one to be a map which find the user"s location
I am a beginner.... thank you all when I learn I am going to help others :))
I don't see that you define the switchView: method anywhere, so it's no surprise that you get a warning about this.

Why is didFindPlacemark never hit?

I am struggling with getting my MKReverseGeocoder to actually finish. This is what I do:
// reverse geocode the user location
geocoder = [[[MKReverseGeocoder alloc] initWithCoordinate:mapView.userLocation.location.coordinate] autorelease];
geocoder.delegate = self;
[geocoder start];
The userLocation coordinate IS valid, I know that. I have didFindPlacemark and didFailWithError, and neither of those are hit...
Either I have the delegate set up wrong or I have no idea...Here's the header:
#interface E_85AppDelegate : UIViewController <UIApplicationDelegate, MKMapViewDelegate, MKReverseGeocoderDelegate, CLLocationManagerDelegate>
{
IBOutlet UIWindow *window;
IBOutlet UITabBarController* tabBarController;
IBOutlet MKMapView* mapView;
IBOutlet MKReverseGeocoder* geocoder;
// other class members...
}
Any ideas?
Evidently my understanding of autorelease is not very good. It releases the geocoder before didFindPlacemark is ever sent the message.

Error: CLLocationManager headingAvailable

I have the following code:
In my .h-Header-File:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface Compass : UIViewController <CLLocationManagerDelegate> {
[...]
CLLocationManager *locationManager;
}
[...]
#property(nonatomic, retain) CLLocationManager *locationManager;
#end
And my .m-File:
#import "[FILENAME].h"
[...]
#synthesize locationManager;
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
if(locationManager.headingAvailable == NO) {
[...]
}
[...]
}
And I get the following error Message for "locationManager.headingAvailable":
error:request for member 'headingAvailable' in something not a structure or union
I've added the CoreLocation framework to my app...
Who can help me?
This property available in iPhone OS 3.0 and later.
May be you try to use it in 2.2.1 ?