IOS 7でうまく機能した私のアプリは、iOS 8 SDKでは機能しません。
CLLocationManager
は場所を返しません、そして私は Settings - > Location Services の下に私のアプリが表示されません。この問題についてGoogleで検索したが、何も起こらなかった。何が間違っている可能性がありますか?
私は自分の問題を解決することになりました。
どうやらiOS 8 SDKでは、位置の更新を開始する前にrequestAlwaysAuthorization
(バックグラウンドロケーションの場合)またはrequestWhenInUseAuthorization
(フォアグラウンドの場合のみロケーション)呼び出しCLLocationManager
が必要です。
NSLocationAlwaysUsageDescription
またはNSLocationWhenInUseUsageDescription
キーがInfo.plist
にあり、プロンプトにメッセージが表示される必要もあります。これらを追加することで問題が解決しました。
それが他の誰かに役立つことを願っています。
編集:より詳細な情報については、以下をご覧ください。 Core-Location-Manager-Changes-in-ios-8
私は同じ問題で髪を引き抜いていました。 Xcodeはあなたにエラーを与えます:
位置認証を求めずに
MapKit
位置の更新を開始しようとしています。最初に-[CLLocationManager requestWhenInUseAuthorization]
または-[CLLocationManager requestAlwaysAuthorization]
を呼び出す必要があります。
ただし、上記の方法のいずれかを実装しても、info.plistにNSLocationAlwaysUsageDescription
またはNSLocationWhenInUseUsageDescription
のエントリがない限り、ユーザーに確認することはありません。
次の行をinfo.plistに追加します。文字列の値は、ユーザーの場所にアクセスする必要がある理由を表しています。
<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
私はこのプロジェクトをXcode 5で始めてからこれらのエントリが見つからなかったと思います。
これら2つの設定の詳細情報を見つけることができます ここ
これがiOS 7との後方互換性を確保するために、ユーザーがiOS 8またはiOS 7を実行しているかどうかを確認する必要があります。次に例を示します。
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
//In ViewDidLoad
if(IS_OS_8_OR_LATER) {
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
- (void)startLocationManager
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
[locationManager requestWhenInUseAuthorization]; // Add This Line
}
そしてあなたのinfo.plistファイルへ
アップルの資料によると:
IOS 8以降、アプリのInfo.plistファイルにNSLocationWhenInUseUsageDescription
またはNSLocationAlwaysUsageDescription
キー値が存在する必要があります。その場合は、必要に応じて[self.myLocationManager requestWhenInUseAuthorization]
または[self.myLocationManager requestAlwaysAuthorization]
を呼び出して、ロケーションの更新を登録する前にユーザーに許可を要求する必要もあります。 Info.plistに入力した文字列は次のダイアログに表示されます。
ユーザーが許可を与えた場合、それは通常通りの仕事です。彼らが許可を拒否した場合、デリゲートはロケーションの更新について通知されません。
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
NSUInteger code = [CLLocationManager authorizationStatus];
if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
// choose one request according to your business.
if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
[self.locationManager requestAlwaysAuthorization];
} else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
[self.locationManager requestWhenInUseAuthorization];
} else {
NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
}
}
}
[self.locationManager startUpdatingLocation];
}
> #pragma mark - CLLocationManagerDelegate
- (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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(@"didUpdateToLocation: %@", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
}
}
IOS 8では、位置情報を機能させるために2つの追加作業を行う必要があります。Info.plistにキーを追加し、それを開始するように要求する位置情報マネージャーから承認を要求します。新しい位置認証には2つのInfo.plistキーがあります。これらのキーの一方または両方が必要です。どちらのキーもない場合は、startUpdatingLocationを呼び出すことができますが、ロケーションマネージャは実際には起動しません。失敗メッセージを代理人に送信することもできません(開始されていないので失敗することはありません)。一方または両方のキーを追加しても、明示的に承認を要求するのを忘れた場合も失敗します。だからあなたがする必要がある最初の事はあなたのInfo.plistファイルに次のキーの一方または両方を追加することです:
これらのキーは両方とも文字列を取ります。
これはあなたが位置情報サービスを必要とする理由の説明です。 iOS 7の場合と同様に、InfoPlist.stringsファイルにローカライズすることができる「現在地を特定するには場所が必要です」などの文字列を入力できます。
Xcode 5でコンパイルできる私の解決策:
#ifdef __IPHONE_8_0
NSUInteger code = [CLLocationManager authorizationStatus];
if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
// choose one request according to your business.
if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
[self.locationManager requestAlwaysAuthorization];
} else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
[self.locationManager requestWhenInUseAuthorization];
} else {
NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
}
}
#endif
[self.locationManager startUpdatingLocation];
場所を尋ねるための古いコードはiOS 8では動作しません。あなたは位置認証のためにこのメソッドを試すことができます:
- (void)requestAlwaysAuthorization
{
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
// If the status is denied or only granted for when in use, display an alert
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusDenied) {
NSString *title;
title = (status == kCLAuthorizationStatusDenied) ? @"Location services are off" : @"Background location is not enabled";
NSString *message = @"To use background location you must turn on 'Always' in the Location Services Settings";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Settings", nil];
[alertView show];
}
// The user has not enabled any location services. Request background authorization.
else if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestAlwaysAuthorization];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
// Send the user to the Settings for this app
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}
}
IOS 8では、位置情報を機能させるためにさらに2つのことを行う必要があります。Info.plistにキーを追加し、それを開始するように要求する位置情報マネージャーに承認を要求します。
info.plist:
<key>NSLocationUsageDescription</key>
<string>I need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need location</string>
これをあなたのコードに追加
if (IS_OS_8_OR_LATER)
{
[locationmanager requestWhenInUseAuthorization];
[locationmanager requestAlwaysAuthorization];
}
Swift開発者にとっての一般的なエラー:
まず、NSLocationWhenInUseUsageDescription
またはNSLocationAlwaysUsageDescription
のいずれかの値を必ずplistに追加してください。
still の場合、ポップアップが承認を求めてくるのが表示されない場合は、View ControllerのviewDidLoad
メソッドにvar locationManager = CLLocationManager()
行を追加しているかどうかを確認してください。そうした場合、locationManager.requestWhenInUseAuthorization()
を呼び出しても何も表示されません。これは、viewDidLoadが実行された後、locationManager変数の割り当てが解除される(クリアされる)ためです。
解決策は、クラスメソッドの先頭にvar locationManager = CLLocationManager()
という行を見つけることです。
[locationManager startUpdatingLocation];
の前に、iOS8位置情報サービス要求を追加します。
if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
[locationManager requestAlwaysAuthorization];
アプリのInfo.plist
を編集して、ユーザーに表示される文字列値でキーNSLocationAlwaysUsageDescription
を追加します(たとえば、We do our best to preserve your battery life.
)。
アプリが開いている間にのみアプリで位置情報サービスが必要な場合は、次のものを置き換えます。
requestAlwaysAuthorization
とrequestWhenInUseAuthorization
および
NSLocationAlwaysUsageDescription
とNSLocationWhenInUseUsageDescription
。
私はiOS 8にアップグレードされたアプリで作業していましたが、位置情報サービスが機能しなくなりました。あなたはおそらくデバッグエリアに以下のようなエラーが表示されるでしょう。
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
私は最も邪魔にならない手順を実行しました。まずinfo.plistにNSLocationAlwaysUsageDescription
エントリを追加してください。
このキーの値を入力しなかったことに注意してください。これはまだ動作します、そしてこれは社内アプリなので私は心配していません。また、位置情報サービスを使用することを要求するタイトルがすでにあるので、私は何も冗長にしたくありませんでした。
次に、iOS 8用のコンディショナルを作成しました。
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_locationManager requestAlwaysAuthorization];
}
この後、locationManager:didChangeAuthorizationStatus:
メソッドが呼び出されます。
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus: (CLAuthorizationStatus)status
{
[self gotoCurrenLocation];
}
そして今、すべてうまくいきます。いつものように、 ドキュメント をチェックしてください。
下位互換性のある解決策
SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
[self.locationManager respondsToSelector:requestSelector]) {
[self.locationManager performSelector:requestSelector withObject:NULL];
} else {
[self.locationManager startUpdatingLocation];
}
Info.plistにNSLocationWhenInUseUsageDescriptionキーを設定します。
Xcodeの警告を生成しない下位互換性のある解決策:
SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
[self.locationManager respondsToSelector:requestSelector]) {
((void (*)(id, SEL))[self.locationManager methodForSelector:requestSelector])(self.locationManager, requestSelector);
[self.locationManager startUpdatingLocation];
} else {
[self.locationManager startUpdatingLocation];
}
Info.plist
にNSLocationWhenInUseUsageDescription
キーを設定してください。
iOSバージョン11.0以降の場合 :あなたのInfo.plist
にNSLocationAlwaysAndWhenInUseUsageDescription
キーを設定する。他の2つのキーと一緒に。
これはios 8の問題です。これをコードに追加してください
if (IS_OS_8_OR_LATER)
{
[locationmanager requestWhenInUseAuthorization];
[locationmanager requestAlwaysAuthorization];
}
そしてinfo.plistに:
<key>NSLocationUsageDescription</key>
<string>I need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need location</string>
IOS 8でユーザーロケーションにアクセスするには、追加する必要があります。
NSLocationAlwaysUsageDescription in the Info.plist
これはユーザに彼らの現在の位置を得る許可を求めます。
Objective-Cの手順 以下の手順に従ってください。
iOS-11の場合 iOS 11の場合はこの回答を見てください: iOS 11の位置情報アクセス /
2つのキーをplistに追加し、下の画像のようにメッセージを入力する必要があります。
1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
3. NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
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-11の場合 iOS 11の場合はこの回答を見てください: iOS 11の位置情報アクセス /
2つのキーをplistに追加し、下の画像のようにメッセージを入力する必要があります。
1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
3. NSLocationAlwaysUsageDescription
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
}
Xamarin を使用している人は、Xamarin 5.5.3 Build 6またはXCode 6.1のドロップダウンでは使用できなかったため、キーNSLocationWhenInUseUsageDescription
を手動でinfo.plistに追加する必要がありました - NSLocationUsageDescription
のみそのリスト、そしてそれはCLLocationManager
を静かに失敗させ続けました。
IOS9でも同様のエラーが出ます(Xcode 7とSwift 2を使って作業しています): ロケーション認証を要求せずにMapKitロケーションの更新を開始しようとしています。 チュートリアルに従って、先生はiOS8とSwift 1.2を使っていました。 Xcode 7とSwift 2にいくつかの変更があります、私はこのコードを見つけました、そして、それは私のためにうまく働きます(誰かが助けを必要とするなら):
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
// MARK: Properties
@IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
}
// MARK: - Location Delegate Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
self.mapView.setRegion(region, animated: true)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Errors: " + error.localizedDescription)
}
}
最後に、私はinfo.plistにそれを置く:情報プロパティリスト: NSLocationWhenInUseUsageDescription 値: アプリはスタッフのためにロケーションサーバーが必要です
Cocoa Keys を常に最新の情報に更新してください。ここにリンクがあります。
楽しい。
IOSのユーザーの場所にアクセスするために。 2つのキーを追加する必要があります
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
info.plistファイルに入れます。
<key>NSLocationWhenInUseUsageDescription</key>
<string>Because I want to know where you are!</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Want to know where you are!</string>
下の画像を見てください。
1つ以上のInfo.plistファイルを持っているあなたのすべてのための小さなヘルパー...
find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Add NSLocationWhenInUseUsageDescription string' {}
現在のディレクトリ(およびサブフォルダ)内のすべてのInfo.plistファイルに必要なタグを追加します。
もう一つは:
find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Set NSLocationWhenInUseUsageDescription $YOURDESCRIPTION' {}
説明がすべてのファイルに追加されます。
// ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string
self.locationManager = [[CLLocationManager alloc] init];
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(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
// Location Manager Delegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"%@", [locations lastObject]);
}
各ターゲットからの各info.plist
にGPSを使用するように求める文字列を含むキーNSLocationWhenInUseUsageDescription
またはNSLocationAlwaysUsageDescription
(バックグラウンドGPS使用)を追加します。
実行して許可を求めます。
[self initLocationManager:locationManager];
initLocationManager
は次のとおりです。
// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{
locationManager = [[CLLocationManager alloc]init];
if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
[locationManager requestAlwaysAuthorization];
}
キーが各ターゲットの各info.plist
にない場合、アプリはユーザーに問い合わせません。 if
はiOS 7との互換性を提供し、respondsToSelector:
メソッドはiOS 7と8の問題を解決するだけでなく将来の互換性を保証します。
私にとっての問題は、CLLocationManagerDelegate
であるクラスが非公開であるため、すべてのデリゲートメソッドを呼び出すことができなかったことです。それは非常に一般的な状況ではないと思いますが、tが誰かを助けてくれるのであれば私はそれを言及すると思いました。
これらのキーをiOS 8.4、iPad mini 2のInfoPlist.strings
に追加します。それも動作します。 Info.plist
にNSLocationWhenInUseUsageDescription
などのキーを設定していません。
InfoPlist.strings:
"NSLocationWhenInUseUsageDescription" = "I need GPS information....";
このスレッドのベース 、それは言った、as in iOS 7
、InfoPlist.stringsでローカライズすることができます。私のテストでは、これらのキーはファイルInfoPlist.strings
で直接設定できます。
したがって、最初に行う必要があるのは、Info.plistファイルに次のキーの1つまたは両方を追加することです。
- NSLocationWhenInUseUsageDescription
- NSLocationAlwaysUsageDescription
これらのキーは両方とも、位置情報サービスが必要な理由の説明である文字列を取ります。 「現在地を確認するには場所が必要です」などの文字列を入力できます。iOS 7のように、InfoPlist.stringsでローカライズできますファイル。
UPDATE:
@IOS
の方法の方が良いと思います。 空の値でInfo.plist
にキーを追加し、InfoPlist.strings
にローカライズされた文字列を追加します。