web-dev-qa-db-ja.com

iOS 8 Mapkit Objcはユーザーの場所を取得できません

IOS 8で、SwiftではなくObj-Cを使用してMap Kitを使用しています。 0.00、0.00に設定されているデバイスの場所を取得できず、エラーが発生しています。

Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.

私は実装しました:(一度に1つだけ試してみましたが、運はありません)

if(IS_OS_8_OR_LATER) {
    [self.locationManager requestWhenInUseAuthorization];
    [self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation]; 

そして、info.plistで

NSLocationWhenInUseUsageDescription  :   App would like to use your location.
NSLocationAlwaysUsageDescription  :  App would like to use your location.

アプリが現在地を使用することを許可するように求められますが、同意した後は何も変更されません。場所は0.00、0.00と表示されています。

ユーザーの場所を表示するためのコード:

//Get Location
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];

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.longitudeDelta = 0.005f;
region.span.longitudeDelta = 0.005f;
[mapView setRegion:region animated:YES];

マイク。

**編集:以下の回答をご覧ください。

51
MBarton

うまくいきました。問題を抱えている他の人を助けるために、以下にコードを投稿しました。

IOS 8でMapKitマップビューを機能させるための完全なコードを次に示します。

AppName-Info.plistに、次のキー名を持つ新しい行を追加します。

NSLocationWhenInUseUsageDescription

または

NSLocationAlwaysUsageDescription

表示したいメッセージの文字列である値で:

YourAppName would like to use your location.

ヘッダーファイル内。 (私はApp Name-Prefix.pchを使用しますが、YourViewController.hも機能します)

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

YourViewController.h

#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>

@interface YourViewController : UIViewController <MKMapViewDelegate,  CLLocationManagerDelegate> {

}


@property(nonatomic, retain) IBOutlet MKMapView *mapView;
@property(nonatomic, retain) CLLocationManager *locationManager;

YourViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.


    mapView.delegate = self;
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    #ifdef __IPHONE_8_0
    if(IS_OS_8_OR_LATER) {
         // Use one or the other, not both. Depending on what you put in info.plist
        [self.locationManager requestWhenInUseAuthorization];
        [self.locationManager requestAlwaysAuthorization];
    }
    #endif
    [self.locationManager startUpdatingLocation];

    mapView.showsUserLocation = YES;
    [mapView setMapType:MKMapTypeStandard];
    [mapView setZoomEnabled:YES];
    [mapView setScrollEnabled:YES];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:YES];

    self.locationManager.distanceFilter = kCLDistanceFilterNone;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [self.locationManager startUpdatingLocation];
    NSLog(@"%@", [self deviceLocation]);

    //View Area
    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.longitudeDelta = 0.005f;
    region.span.longitudeDelta = 0.005f;
    [mapView setRegion:region animated:YES];

}

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
    [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
- (NSString *)deviceLocation {
    return [NSString stringWithFormat:@"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceLat {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.coordinate.latitude];
}
- (NSString *)deviceLon {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceAlt {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.altitude];
}

楽しい!

- マイク

130
MBarton

どこにも書かれていませんが、アプリがMapKitで起動する場合、MBartonの回答を実装した後でも、「場所の認証を求めずにMapKitの場所の更新を開始しようとしています」というエラーメッセージが表示されます。これを回避するには、MapKitの前に新しいView Controllerを作成し、そこにLocation Managerデリゲートを実装する必要があります。 AuthorizationControllerと呼びました。

したがって、AuthorizationController.hで:

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface MCIAuthorizationController : UIViewController <CLLocationManagerDelegate>

@property (strong, nonatomic) CLLocationManager *locationManager;

@end

そしてAuthorizationController.mで:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Location manager
    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];
    }
}

#pragma mark - Location Manager delegates

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    NSLog(@"didUpdateLocations: %@", [locations lastObject]);
}


- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"Location manager error: %@", error.localizedDescription);
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        [self.locationManager startUpdatingLocation];
        [self performSegueWithIdentifier:@"startSegue" sender:self];
    } else if (status == kCLAuthorizationStatusDenied) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location services not authorized"
                                                        message:@"This app needs you to authorize locations services to work."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    } else
        NSLog(@"Wrong location status");
}
8
Rodrigo Pinto

これを試してください:

 (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {

    if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        self.mapView.showsUserLocation = YES;
    }
3
brusnikin

私は同じ問題を抱えていましたが、plistファイルにこれらの2行を追加すると私の問題が解決しました

NSLocationWhenInUseUsageDescription

そして

NSLocationAlwaysUsageDescription

注:これら両方の値の文字列の説明を提供する必要があります。以下のようにコントローラーファイルでそれらのいずれかを使用できます

self.locationManager= [[CLLocationManager alloc] init];
self.locationManager.delegate=self;
[self.locationManager requestAlwaysAuthorization];

この機能にアクセスするには、コントローラーにCLLOcationManagerDelegateを実装する必要があります

2
Aadil Keshwani

コードは問題なく見えますが、requestWhenInUseAuthorizationと他のrequestAlwaysAuthorizationを呼び出す必要はありませんが、必要なものを選択してください。

位置を表示するためのコードは、まだlocationManagerを割り当てているだけで、位置データをすぐに取得することを期待しないでください。

デリゲートメソッドが呼び出されるまで待つ必要があります:-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
、その後self.locationManager.locationも設定されます。

2
PetrV

マイクの答えに加えて、both[self.locationManager requestWhenInUseAuthorization];および[self.locationManager requestAlwaysAuthorization];彼のコードで示されているように動作しません。 [〜#〜] one [〜#〜]のみを使用する必要があります。

APIのより新しい/安定したバージョンでさらにいくつかの変更が行われたと思います。

2
Dean Roccs

受け入れられた答えを拡張し、上記の機能だけでサンプルプロジェクトを作成する場合、CoreLocationおよびMapkitフレームワークとは別に、UIKitFoundationおよびCoreGraphicsフレームワークも手動でXcode 6

0
Deepak Thakur