web-dev-qa-db-ja.com

iOS:アプリは、アプリのインストール中にユーザーの許可を求めていません。毎回kCLAuthorizationStatusNotDeterminedを取得-Objective-c&Swift

IOSアプリでユーザーの場所を取得しようとしています。私は最初にプロジェクトにcorelocationフレームワークを含めました。次に、ボタンをクリックして、以下のようにコアロケーションAPIを呼び出します。これをデバイスにインストールしようとすると、コアロケーションがユーザーに許可を求めません。ボタンのクリックで場所を取得しようとすると、authorizationStatusとしてkCLAuthorizationStatusNotDeterminedが取得されます。これで私を助けてください。何が起こっているのか見当もつかない。

- (IBAction)fetchLessAccurateLocation:(id)sender {
    [self.txtLocation setText:@""];

    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
    locationManager.distanceFilter = 1000;

    if ([self shouldFetchUserLocation]) {
        [locationManager startUpdatingLocation];
    }
}

これは私のshouldFetchUserLocationメソッドです:

-(BOOL)shouldFetchUserLocation{

    BOOL shouldFetchLocation= NO;

    if ([CLLocationManager locationServicesEnabled]) {
        switch ([CLLocationManager authorizationStatus]) {
            case kCLAuthorizationStatusAuthorized:
                shouldFetchLocation= YES;
                break;
            case kCLAuthorizationStatusDenied:
            {
                UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"App level settings has been denied" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
                [alert show];
                alert= nil;
            }
                break;
            case kCLAuthorizationStatusNotDetermined:
            {
                UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The user is yet to provide the permission" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
                [alert show];
                alert= nil;
            }
                break;
            case kCLAuthorizationStatusRestricted:
            {
                UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The app is recstricted from using location services." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
                [alert show];
                alert= nil;
            }
                break;

            default:
                break;
        }
    }
    else{
        UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The location services seems to be disabled from the settings." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
        [alert show];
        alert= nil;
    }

    return shouldFetchLocation;
}

ここに私のコアロケーションデリゲートメソッドがあります。

- (void)locationManager:(CLLocationManager *)manager
    didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0){

    NSLog(@"location fetched in delegate");

    CLLocation* location = [locations lastObject];
    NSDate* eventDate = location.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];

    if (abs(howRecent) < 15.0) {
        // If the event is recent, do something with it.
        NSLog(@"inside loop.... latitude %+.6f, longitude %+.6f\n",
              location.coordinate.latitude,
              location.coordinate.longitude);
    }
    NSLog(@"latitude %+.6f, longitude %+.6f\n",
          location.coordinate.latitude,
          location.coordinate.longitude);
    [self.txtLocation setText:[NSString stringWithFormat:@"\nlatitude: %+.6f \nlongitude:   %+.6f", location.coordinate.latitude, location.coordinate.longitude]];

    [locationManager stopUpdatingLocation];
    [locationManager stopMonitoringSignificantLocationChanges];

    if(locationManager!=nil){
        locationManager.delegate= nil;
        locationManager= nil;
    }
}
70

アプリを再インストールした後、[CLLocationManager authorizationStatus]を確認するたびにkCLAuthorizationStatusNotDeterminedが返され、アプリが[設定]> [プライバシー]> [位置情報サービス]にも表示されないという同じ問題に直面していました。

IOSがユーザーに位置情報サービスへのアクセスを承認するように求める認証ダイアログは、[locationManager startUpdatingLocation]でトリガーされます。この場合、呼び出されることはありません(shouldFetchUserLocationは常にNO)。

Miguel C.の解決策は良い修正のように思えます。

iOS8.xの編集

IOS8が登場したとき、CLLocationManagerの使用方法にほとんど変化はありませんでした。他の回答で何度か言及したように、iOS7と比較して追加の手順が必要です。今日、私は自分で問題に直面し、これを見つけました 記事 (他の複数の質問から参照されていますが、以前の答えは完了しています)。それが役に立てば幸い!

41
David Jirman

iOS8では、LocationsServicesでAPIが大幅に変更されました。

[CLLocationManager locationServicesEnabled]がYESを返すと仮定すると、

IOSアプリの最初の起動[iOS7とiOS8の両方]-locationMangers(CLLocationManager)authorizationStatusプリセットは

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

IOS7 +でのプロンプト

LocationManger(CLLocationManager、Strong)を開始し、デリゲート(CLLocationManagerDelegate)を設定します

ここで、ユーザーにロケーションサービスの使用を促し、[設定]> [プライバシー]> [ロケーションサービス]の下にアプリをリストするように要求します。

ロケーションの更新-[self.locationManager startUpdatingLocation]

RegionMonitoring-[self.locationManager startMonitoringForRegion:beaconRegion]

上記の方法の実行直後に、iOSはアプリでロケーションサービスの使用を許可するようにユーザーに要求し、ユーザー選択アプリに関係なく、設定>プライバシー>ロケーションサービスにリストされます。

IOS8 +でのプロンプト

IOS8と同じケースで、最初にApp Locations Servicesを起動します

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

iOS 8では、ユーザーにプロンプ​​トを表示するための新しい方法がありました

[self.locationManager requestAlwaysAuthorization] 
or
[self.locationManager requestWhenInUseAuthorization]

requestAlwaysAuthorization/requestWhenInUseAuthorizationはiOS8から利用可能です。アプリの展開ターゲットがiOS7の場合、これをifブロックの下にラップして、iOS7でアプリがクラッシュしないようにします。

if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
{
[self.locationManager requestAlwaysAuthorization]; .
}

または

if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}

非常に重要な###:

IOS8により、アプリがrequestAlwaysAuthorization/requestWhenInUseAuthorizationを使用する理由を示す文字列を含めることが必須です。info.plistには、アプリの要件に応じてこれらのプロパティのいずれかが含まれます

kCLAuthorizationStatusAuthorizedAlwaysにはKey/Value(string Value)ペアが常に含まれます

NSLocationAlwaysUsageDescription = App use Locations service mode Always

kCLAuthorizationStatusAuthorizedWhenInUseには、キー/値(文字列値)のペアが含まれます

NSLocationWhenInUseUsageDescription = App use Locations service mode In Use 

Info.plistのスクリーンショット(誰かがこれで混乱している場合) enter image description here

101
Rithesh Rao

Objective-C以下の指示に従ってください:

iOS-11iOS 11については、この回答をご覧ください: iOS 11ロケーションアクセス

2つのキーをplistに追加し、次の画像のようにメッセージを提供する必要があります。

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription

enter image description hereiOS-10以下:

NSLocationWhenInUseUsageDescription

enter image description here

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
    [locationManager requestWhenInUseAuthorization];
}else{
    [locationManager startUpdatingLocation];
} 

デリゲートメソッド

#pragma mark - Lolcation Update 
- (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 didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
        case kCLAuthorizationStatusRestricted:
        case kCLAuthorizationStatusDenied:
        {
            // do some error handling
        }
            break;
        default:{
            [locationManager startUpdatingLocation];
        }
            break;
    }
}
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations lastObject];
    userLatitude =  [NSString stringWithFormat:@"%f", location.coordinate.latitude] ;
    userLongitude =  [NSString stringWithFormat:@"%f",location.coordinate.longitude];
    [locationManager stopUpdatingLocation];
}

スイフトコード

以下の指示に従ってください。

iOS-11iOS 11については、この回答をご覧ください: iOS 11ロケーションアクセス

2つのキーをplistに追加し、次の画像のようにメッセージを提供する必要があります。

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription

enter image description hereiOS-10以下:

enter image description here

import CoreLocation
class ViewController: UIViewController ,CLLocationManagerDelegate {
var locationManager = CLLocationManager()

//MARK- Update Location 
func updateMyLocation(){
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
    if locationManager.respondsToSelector(#selector(CLLocationManager.requestWhenInUseAuthorization)){
       locationManager.requestWhenInUseAuthorization()
    }
    else{
        locationManager.startUpdatingLocation()
    }
}

デリゲートメソッド

//MARK: Location Update
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
    NSLog("Error to update location :%@",error)
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    switch status {
    case .NotDetermined: break
    case .Restricted: break
    case .Denied:
            NSLog("do some error handling")
        break
    default:
        locationManager.startUpdatingLocation()
    }
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
     let location = locations.last! as CLLocation
    var latitude = location.coordinate.latitude
    var longitude = location.coordinate.longitude

}
29
Alok

NSLocationWhenInUseUsageDescriptionを追加する必要がありますinfo.plist。それは少し奇妙ですが、テキストなしで文字列値として追加してから、場所を開始したいときは:

CLLocationManager * locationManager = [[CLLocationManager alloc] init];

[locationManager requestWhenInUseAuthorization];
17
LemonandlIme

IOS8でこの問題に直面した場合は、:requestWhenInUseAuthorization。を使用してください

12
Abhilash Gopal

IOS 8では、位置情報を機能させるために、さらに2つのことを行う必要があります。Info.plistにキーを追加し、ロケーションマネージャーに開始を要求する承認を要求します。新しいロケーション認証用の2つのInfo.plistキーがあります。これらのキーの一方または両方が必要です。どちらのキーも存在しない場合は、startUpdatingLocationを呼び出すことができますが、ロケーションマネージャーは実際には起動しません。デリゲートにも失敗メッセージは送信されません(開始されたことがないため失敗することはありません)。また、一方または両方のキーを追加したが、許可を明示的に要求することを忘れた場合にも失敗します。

したがって、最初に行う必要があるのは、Info.plistファイルに次のキーの1つまたは両方を追加することです。

NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription

これらのキーは両方とも、ロケーションサービスが必要な理由の説明である文字列を取ります。 「現在地を確認するには場所が必要です」などの文字列を入力できます。iOS7のように、InfoPlist.stringsファイルでローカライズできます。

次に、対応するロケーションメソッドWhenInUseまたはBackgroundの承認を要求する必要があります。次の呼び出しのいずれかを使用します。

[self.locationManager requestWhenInUseAuthorization]
[self.locationManager requestAlwaysAuthorization]

詳細 の場合。

6

IOS 7がリリースされてから、Rashmi Ranjan mallickがコメントで数回言った問題がありました。 iOS 7のバグの1つだと思いますが、iOSの新バージョンにはそれらがたくさんあります。

私にとって問題は同じでした:

1.アプリを開き、場所について尋ねることはありません。 iOSは許可を求めていませんでした
2. [設定]-> [プライバシー]-> [位置情報サービス]に移動しましたが、アプリがありませんでした。
3。アプリの場所の許可を変更することができませんでした。

そのための1つの回避策は次のとおりです。

1.アプリを削除します。
2。メインスイッチボタンですべての位置情報サービスを無効にします。
3。アプリに再度アクセスします。
4。アプリを殺します。
5。前の切り替えボタンで位置情報サービスを再度有効にします。
6。それでもリストに表示されない場合は、アプリに再度アクセスし、再度強制終了して、設定に戻ります。
7。そこにあるはずです。

これは私にとってはうまくいきました。これが役に立つことを願っています。

更新: if iOS 8requestWhenInUseAuthorizationまたはrequestAlwaysAuthorizationを呼び出していることを確認してください

このコードに従うことができます::)

#ifdef __IPHONE_8_0
    if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
    {
        if([[Wave_SettingsObject sharedObject] backgroundLocationEnabled].boolValue == YES)
        {
            if(![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"])
            {
                NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription key");
            }

            if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) //iOS 8+
            {
                [locationManager requestAlwaysAuthorization];
            }
        }
        else if([[Wave_SettingsObject sharedObject] isLocationEnabled].boolValue == YES)
        {
            if(![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"])
            {
                NSLog(@"Info.plist does not contain NSLocationWhenInUseUsageDescription key");
            }

            if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) //iOS 8+
            {
                [locationManager requestWhenInUseAuthorization];
            }

        }
    }
#endif
3
Jesuslg123

アプリをアンインストールして、もう一度実行してください。

うまくいかなかった場合は、設定に移動して、そのアプリの認証を無効にします。その後、再度実行して、許可を求めているかどうかを確認します。

または:

次のようなコードを使用して、アプリに強制的に場所の監視を開始させることができます。

self.locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];

デリゲートメソッドでは、場所の取得中にエラーがあるかどうかを検出でき、ユーザーに通知できます。

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    // Delegate of the location manager, when you have an error
    NSLog(@"didFailWithError: %@", error);

    UIAlertView *errorAlert = [[UIAlertView alloc]     initWithTitle:NSLocalizedString(@"application_name", nil) message:NSLocalizedString(@"location_error", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles:nil];

    [errorAlert show];
}

質問があれば教えてください。

2
Miguel Chaves

追加してみてください

[locationManager startUpdatingLocation]

位置情報サービスがオンになっていることも確認してください。

編集:

また、アプリケーションを削除して再インストールしてみてください。アプリが現在位置を使用する許可を求めていないことを読んでいるという記録があるかもしれません。

1
Bot

場所の入力を求めるときは、それらのことを忘れてはいけません(iOS 8以降):

  1. アプリのinfo.plistにこのフラグを追加します。NSLocationAlwaysUsageDescriptionまたはNSLocationWhenInUseUsageDescriptionは、常に場所にアクセスするか、アプリが使用中の場合にのみ使用します(常にアクセスする必要がない場合は2番目をお勧めします)。 これは新しくて奇妙なため、最も重要です
  2. 常に許可をリクエストする場合は、ターゲット機能のバックグラウンドモードとして位置情報の更新を追加することを忘れないでください
  3. ロケーションマネージャーを初期化するときに適切な許可を求めていることを確認します。

    -(void)initLocationManager{
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate=self;
    
        [locationManager requestAlwaysAuthorization]; // HERE ASK FOR THE RELEVANT
    }
    

シミュレーターでテストするには、オプションから「すべてのコンテンツと設定をリセットする」ことをお勧めします。これは、アプリの新しいユーザーが取得するのとまったく同じエクスペリエンスを取得する唯一の方法です。

1
Idan

同様の問題がありましたが、原因は異なります。他の人を助けることができる場合に備えて、ここに追加します。

承認メッセージの受信を停止しました。他の回答に記載されている要件が満たされる前に機能していたため、plistのキー、承認ステータスを確認してからios8 +で許可を要求します。

私の場合、問題は「アクセスガイド」モードに関連していました。これはキオスク用のアプリであり、「アクセスガイド」がアクティブになった後にのみビーコンの範囲を開始します。ただし、このモードでは許可メッセージの要求は送信されないようです。最初に表示されたビューのDidLoadに承認手続きを移動するだけで修正できました。

カメラを使用するリクエストでも同じことが起こります。

1
Juan Valera

私はこの問題に遭遇し、pListキーを含む必要なものをすべて実装しましたが、私のアプリはまだ場所を要求していませんでした。

問題は、locationManager変数をローカルにすることができないということでした-インスタンス変数である必要があります。

の代わりに

-(void) updateLocation {
   CLLocationManager *locationManager = ...
}

それが必要です:

CLLocationManager *locationManager;

-(void) updateLocation {
  self.locationManager = ...
}
1