Dịch vụ định vị không hoạt động trong iOS 8


608

Ứng dụng của tôi hoạt động tốt trên iOS 7 không hoạt động với SDK iOS 8.

CLLocationManagerkhông trả lại vị trí và tôi cũng không thấy ứng dụng của mình trong Cài đặt -> Dịch vụ vị trí . Tôi đã thực hiện một tìm kiếm Google về vấn đề này, nhưng không có gì xuất hiện. điều gì sai?


Bạn cũng có thể sử dụng ứng dụng này làm ứng dụng tham khảo cho giải pháp github.com/jbanford/ConstantLocationUpdates
ashok vadeelsu

19
Tôi đã đăng về một số thay đổi đối với trình quản lý vị trí trong iOS 8 tại đây: nevan.net/2014/09/core-location-manager-changes-in-ios-8
vua nevan

2
Bạn có thể thử sử dụng thư viện này để đơn giản hóa API vị trí cốt lõi và hiển thị giao diện dựa trên các khối đẹp và bình thường hóa tất cả sự khác biệt giữa các phiên bản iOS khác nhau (Tiết lộ đầy đủ: Tôi là tác giả): github.com/lmirosevic/GBLocation
lms

Tôi tìm thấy một số tài liệu tham khảo ở đây datacalculation.blogspot.in/2014/11/ trên
Thử nghiệm iOS

2
@nevanking Bạn ạ! cần một vương miện! Tôi đã chiến đấu với vấn đề này kể từ khi thay đổi và vẫn chưa tìm được "hướng dẫn" cách khắc phục, nó rất thân thiện .. Hướng dẫn của bạn đã khiến một kẻ ngốc như tôi, tự xử lý vấn đề. Cảm ơn bạn rất nhiều vì liên kết đó.
Patrick R

Câu trả lời:


1086

Tôi đã kết thúc giải quyết vấn đề của riêng tôi.

Rõ ràng trong SDK iOS 8, requestAlwaysAuthorization(đối với vị trí nền) hoặc requestWhenInUseAuthorization(chỉ vị trí khi tiền cảnh) gọi CLLocationManagerlà cần thiết trước khi bắt đầu cập nhật vị trí.

Cũng cần phải có NSLocationAlwaysUsageDescriptionhoặc nhập NSLocationWhenInUseUsageDescriptionvào Info.plistvới một thông báo sẽ được hiển thị trong lời nhắc. Thêm những giải quyết vấn đề của tôi.

nhập mô tả hình ảnh ở đây

Hy vọng nó sẽ giúp người khác.

EDIT: Để biết thêm thông tin, hãy xem tại: Core-Location-Manager-Change-in-ios-8


6
bạn có thể chia sẻ chính xác các thông tin cập nhật trong Info.plist không? Tôi không thể thấy khóa đó trong Info.plist của tôi. Tôi đã thêm nó và dường như nó không hoạt động. Tôi đang sử dụng Swift, iOS8 và XCode 6 beta 4
Vijay Kumar AB

4
@Vjay - bạn phải chỉnh sửa tệp Info.plist trong trình chỉnh sửa, không thể đặt các khóa đó trong Xcode (kể từ phiên bản beta 6).
Kendall Helmstetter Gelner

11
Xin nhắc lại, nếu bạn không muốn hiển thị lời giải thích tùy chỉnh cho người dùng, chỉ cần đặt khóa này thành một chuỗi trống.
men

7
Bạn cần giữ lại vị trí Trình quản lý để làm cho nó hoạt động. vì vậy hãy biến CLLocationManager của bạn thành một tài sản mạnh mẽ
Vassily

273
Tôi 'YÊU' rằng bạn không nhận được lỗi, không cảnh báo, không có thông điệp tường trình, KHÔNG NÊN nếu bạn rời khỏi mục nhập chính. Về cơ bản, Apple đã tạo một lệnh gọi API KHÔNG CÓ nếu bạn không có mục nhập chính. Cảm ơn @OrtwinGentz ​​đã tìm ra điều này.
MobileVet

314

Tôi đã kéo tóc ra với cùng một vấn đề. Xcode cung cấp cho bạn lỗi:

Cố gắng bắt đầu MapKitcập nhật vị trí mà không yêu cầu ủy quyền vị trí. Phải gọi -[CLLocationManager requestWhenInUseAuthorization]hoặc -[CLLocationManager requestAlwaysAuthorization]trước.

Nhưng ngay cả khi bạn triển khai một trong các phương pháp trên, nó sẽ không nhắc người dùng trừ khi có một mục trong thông tin.plist cho NSLocationAlwaysUsageDescriptionhoặc NSLocationWhenInUseUsageDescription.

Thêm các dòng sau vào thông tin của bạn.plist trong đó các giá trị chuỗi đại diện cho lý do bạn cần truy cập vào vị trí người dùng

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>

Tôi nghĩ rằng các mục này có thể đã bị thiếu kể từ khi tôi bắt đầu dự án này trong Xcode 5. Tôi đoán Xcode 6 có thể thêm các mục mặc định cho các khóa này nhưng chưa được xác nhận.

Bạn có thể tìm thêm thông tin về hai Cài đặt này tại đây


13
xcode 6 không thêm các khóa này theo mặc định, nếu bạn có ý định triển khai CLLocationManager, bạn phải thêm chúng theo cách thủ công
Wesley Smith

1
Tôi cũng đã phải thêm chúng theo cách thủ công, không thể thêm thông qua chế độ xem RawValues ​​của info.plist trong Xcode6!
Kendall Helmstetter Gelner

1
Tôi đã tìm kiếm mãi mãi cho điều này. Thông báo [CLLLocationManager ủy quyềnStatus] của tôi chỉ trả về giá trị <nil>. Sau khi thêm các phím trên, nó bắt đầu trả về các liệt kê tương ứng cho đầu ra của tin nhắn. Từ những gì tôi tìm thấy đây là một lỗi iOS 8 đã biết nhưng không thể tìm thấy bất cứ điều gì trong ngữ cảnh của tôi từ lâu. Cảm ơn một triệu!
MrOli3000

4
Tôi thích giá trị chuỗi bạn đặt vào
Chris Chen

1
Thông báo sẽ xuất hiện dưới dạng tin nhắn phụ trong Thông báo hỏi liệu người dùng có muốn chia sẻ vị trí của họ hay không. Như vậy, chỉ đơn giản là trống (trống) dường như có ý nghĩa nhất trong ứng dụng của tôi. Một lời giải thích về lý do tại sao bạn muốn sử dụng vị trí cũng sẽ có ý nghĩa. Tuy nhiên, NSLocationWhenInUseUsageDes mô tả đã không hoạt động như mong đợi đối với tôi (nghĩa là tiếp tục bị từ chối, mặc dù giá trị trả về là chính xác). NSLocationAlwaysUsageDes mô tả hoạt động tốt.
bobady hồ quang

104

Để đảm bảo rằng tính năng này tương thích ngược với iOS 7, bạn nên kiểm tra xem người dùng đang chạy iOS 8 hay iOS 7. Ví dụ:

#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];

164
Một cách tốt hơn so với việc kiểm tra phiên bản là kiểm tra xem liệu đối tượng có bộ chọn đó hay không, ví dụ: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
progrmr

1
Tôi gặp khó khăn khi thực hiện giải pháp của @ progrmr khi xây dựng trên Xcode 5, vì nó không biết requestAlwaysAuthorizationphương thức này là gì. Giải pháp bổ sung của tôi là sử dụng dòng này trong ifcâu lệnh thay vì gọi phương thức thông thường : [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. Có thể điều này là hiển nhiên đối với những người khác, nhưng tôi phải mất một thời gian để tìm ra. Tôi nghĩ đó là giải pháp phù hợp cho đến khi Xcode 6 cuối cùng được phát hành.
VinceFior

2
Giải pháp phù hợp là xây dựng với Xcode 6. Nếu bạn đang xây dựng với Xcode 5, bạn không cần phải yêu cầu ủy quyền, nó sẽ tự động.
progrmr

Bạn có thể có một điểm. Mối quan tâm của tôi là tôi muốn mã của mình biên dịch trong Xcode 5 (mặc dù nó không hoạt động trên iOS 8 trừ khi được biên dịch trong Xcode 6) trong khi nhóm của tôi chuyển sang Xcode 6. Nhưng có lẽ đó là một quy trình làm việc tốt hơn để viết mã bình thường và không hợp nhất nó cho đến khi chúng tôi chuyển sang Xcode 6 .. Cảm ơn.
VinceFior

@VinceFior cách tiếp cận được đề xuất là biên dịch có điều kiện bằng cách sử dụng macro được xác định SDK __IPHONE_OS_VERSION_MAX_ALLOWED( #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
Steven Kramer

50
- (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


}

Và đến tập tin info.plist của bạn nhập mô tả hình ảnh ở đây


1
Tìm thấy giải pháp tương tự theo cách mô tả hơn tại datacalculation.blogspot.in/2014/11/ trên
Thử nghiệm iOS

2
@Hemang: Theo Tài liệu Apple Dev: Sẽ an toàn khi bắt đầu dịch vụ định vị trước khi trạng thái ủy quyền của ứng dụng của bạn được xác định. Mặc dù bạn có thể bắt đầu dịch vụ định vị, các dịch vụ đó không cung cấp bất kỳ dữ liệu nào cho đến khi trạng thái ủy quyền thay đổi thành kCLAuthorizationStatusAuthorizedAlways hoặc kCLAuthorizationStatusAuthorizedWhenInUse.
Andrew

Hơi muộn một chút, nhưng tôi khuyên bạn nên ẩn các phần không liên quan trong tệp plist của mình, đặc biệt là FacebookAppID
Przemysław Wrzesiński

Cảm ơn Nhưng đó chỉ là một mẫu giả :)
neo D1

Điều quan trọng nữa là dự án đang trỏ đến đúng thông tin.plist (một trong đó khóa được xác định). Điều đó được xác định trong cài đặt xây dựng dự án trong Info.plist File.
chiếu sáng

30

Theo tài liệu của Apple:

Kể từ iOS 8, cần có sự hiện diện của một NSLocationWhenInUseUsageDescriptionhoặc một NSLocationAlwaysUsageDescriptiongiá trị chính trong tệp Info.plist của ứng dụng của bạn. Sau đó, cũng cần phải yêu cầu sự cho phép của người dùng trước khi đăng ký cập nhật vị trí, bằng cách gọi [self.myLocationManager requestWhenInUseAuthorization]hoặc[self.myLocationManager requestAlwaysAuthorization] tùy theo nhu cầu của bạn. Chuỗi bạn đã nhập vào Info.plist sau đó sẽ được hiển thị trong hộp thoại tiếp theo.

Nếu người dùng cấp phép, đó là kinh doanh như bình thường. Nếu họ từ chối cấp phép, thì đại biểu không được thông báo về cập nhật vị trí.


Tôi tìm thấy mô tả đơn giản ở đây tại datacalculation.blogspot.in/2014/11/ trên
Thử nghiệm iOS

28
- (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];
        }
    }

Trong iOS 8, bạn cần thực hiện thêm hai điều để hoạt động của vị trí: Thêm khóa vào Info.plist của bạn và yêu cầu ủy quyền từ trình quản lý vị trí yêu cầu bắt đầu. Có hai khóa Info.plist cho ủy quyền vị trí mới. Một hoặc cả hai phím này là bắt buộc. Nếu không có phím nào ở đó, bạn có thể gọi startUpdatingLocation nhưng trình quản lý vị trí sẽ không thực sự bắt đầu. Nó sẽ không gửi tin nhắn thất bại cho đại biểu (vì nó không bao giờ bắt đầu, nên nó không thể thất bại). Nó cũng sẽ thất bại nếu bạn thêm một hoặc cả hai khóa mà quên yêu cầu ủy quyền rõ ràng. Vì vậy, điều đầu tiên bạn cần làm là thêm một hoặc cả hai khóa sau vào tệp Info.plist của bạn:

  • NSLocationWhenInUseUsage Mô tả
  • NSLocationAlwaysUsageDes mô tả

Cả hai khóa này đều có một chuỗi

đó là một mô tả về lý do tại sao bạn cần dịch vụ định vị. Bạn có thể nhập một chuỗi như Vị trí của Bắt buộc để tìm ra vị trí của bạn, như trong iOS 7, có thể được bản địa hóa trong tệp InfoPlist.strings.

nhập mô tả hình ảnh ở đây


19

Giải pháp của tôi có thể được biên dịch trong 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];

2
Giải pháp năng động đẹp, để sử dụng trong tất cả các ứng dụng. Tôi sẽ thay đổi thứ tự mặc dù và thay vì kiểm tra iphone 8.0, tôi sẽ kiểm tra xem trình quản lý vị trí có phản hồi ủy quyền hay không và sau đó chạy ủy quyền để lấy mã. Điều này sẽ làm cho nó phổ quát hơn.
zirinisp

Làm việc trên xCode 7.2 là tốt.
Totoro

17

Mã cũ để hỏi vị trí sẽ không hoạt động trong iOS 8. Bạn có thể thử phương pháp này để ủy quyền vị trí:

- (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];
    }
}

UIAlertView đã không được chấp nhận. Bạn nên sử dụng UIAlertControll thay thế.
Pasan Premaratne

vâng tôi biết nó không dùng nữa nhưng nó cũng sẽ hoạt động. nhưng có tốt hơn sử dụng UIAlertControll cho IOS8.
Nits007ak

12

Trong iOS 8, bạn cần thực hiện thêm hai điều để hoạt động của vị trí: Thêm khóa vào Info.plist của bạn và yêu cầu ủy quyền từ trình quản lý vị trí yêu cầu bắt đầu

thông tin.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>

Thêm mã này vào mã của bạn

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

1
không rõ mã giả của bạn là cuộc gọi tiền xử lý hay cuộc gọi thông thường
El Dude

1
Thêm tệp này vào tệp constants.h hoặc .pch của bạn: #define IS_OS_8_OR_LATER ([[UIDevice currentDevice] .systemVersion floatValue]> = 8.0)
OxenBoxen

Tại sao bạn yêu cầu cả hai, bạn chỉ nên thêm một nhận xét đề cập để sử dụng cái này hay cái kia tùy thuộc vào nhu cầu ứng dụng của bạn
powerj1984

phần info.plist đủ dễ thực hiện trong Unity3d, nhưng tôi sẽ thêm phần mã như thế nào nếu sử dụng unity3d? Ở đâu ?
CthulhuJon

11

Một lỗi phổ biến cho các nhà phát triển Swift:

Trước tiên, hãy đảm bảo bạn thêm một giá trị cho số nguyên cho NSLocationWhenInUseUsageDescriptionhoặc NSLocationAlwaysUsageDescription.

Nếu bạn vẫn không thấy cửa sổ bật lên yêu cầu ủy quyền, hãy xem liệu bạn có đang đặt dòng var locationManager = CLLocationManager()trong viewDidLoadphương thức của Trình điều khiển xem không . Nếu bạn làm, sau đó ngay cả khi bạn gọi locationManager.requestWhenInUseAuthorization(), không có gì sẽ hiển thị. Điều này là do sau khi viewDidLoad thực thi, biến locationManager bị hủy (xóa).

Giải pháp là xác định vị trí dòng var locationManager = CLLocationManager()ở đầu phương thức lớp.


9

Trước đó [locationManager startUpdatingLocation];, hãy thêm yêu cầu dịch vụ định vị iOS8:

if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    [locationManager requestAlwaysAuthorization];

Chỉnh sửa ứng dụng của bạn Info.plistvà thêm khóa NSLocationAlwaysUsageDescriptionvới giá trị chuỗi sẽ được hiển thị cho người dùng (ví dụ We do our best to preserve your battery life.:)

Nếu ứng dụng của bạn chỉ cần dịch vụ định vị trong khi ứng dụng đang mở, hãy thay thế:

requestAlwaysAuthorizationvới requestWhenInUseAuthorization

NSLocationAlwaysUsageDescriptionvới NSLocationWhenInUseUsageDescription.


9

Tôi đang làm việc trên một ứng dụng được nâng cấp lên iOS 8 và dịch vụ định vị đã ngừng hoạt động. Bạn có thể sẽ gặp và lỗi trong khu vực Gỡ lỗi như vậy:

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

Tôi đã làm thủ tục ít xâm nhập nhất. Đầu tiên thêm NSLocationAlwaysUsageDescriptionmục vào thông tin của bạn.plist:

Nhập mô tả hình ảnh ở đây

Lưu ý rằng tôi đã không điền vào giá trị cho khóa này. Điều này vẫn hoạt động và tôi không quan tâm vì đây là một ứng dụng nội bộ. Ngoài ra, đã có một tiêu đề yêu cầu sử dụng dịch vụ định vị, vì vậy tôi không muốn làm bất cứ điều gì dư thừa.

Tiếp theo tôi đã tạo một điều kiện cho iOS 8:

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

Sau đó, locationManager:didChangeAuthorizationStatus:phương thức này được gọi:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:  (CLAuthorizationStatus)status
{
    [self gotoCurrenLocation];
}

Và bây giờ mọi thứ hoạt động tốt. Như mọi khi, kiểm tra các tài liệu .


7

Giải pháp với khả năng tương thích ngược:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}

Thiết lập NSLocationWhenInUseUsageDes mô tả trong Info.plist của bạn


2
Điều này là không chính xác, những gì về trường hợp kCLAuthorizationStatusDenied? nó nhảy sang chỗ khác và bắt đầu cập nhật vị trí không chính xác!
electronix384128

@BenMarten Tôi không nghĩ nó quan trọng. Bạn nên tự xử lý với locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error. Tuy nhiên, anh ta đã quên thêm startUpdatingLocation vào câu lệnh if để sau khi họ chấp nhận hoặc từ chối nó, nó không thực sự gọi startUpdateLocation.
Chris

6

Giải pháp với khả năng tương thích ngược không tạo ra cảnh báo 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];
}

NSLocationWhenInUseUsageDescriptionPhím thiết lập trong của bạn Info.plist.

Đối với phiên bản iOS 11.0+ : NSLocationAlwaysAndWhenInUseUsageDescriptionPhím thiết lập trong của bạn Info.plist. cùng với 2 phím khác.


Điều này là không chính xác, những gì về trường hợp kCLAuthorizationStatusDenied? nó nhảy sang chỗ khác và bắt đầu cập nhật vị trí không chính xác!
electronix384128

Điều này khá lạ, điều này hoạt động tốt đối với tôi không ổn hoàn toàn tốt với cả cho phép và không cho phép. Giải pháp của Jacob có vẻ chính xác nhưng không hiệu quả với tôi. Lạ nhưng làm việc !!!
Josh

Gọi [self.locationManager startUpdatingLocation] ngay sau khi requestWhenInUseAuthorization không có điểm nào
Kostia Kim

5

Đây là vấn đề với ios 8 Thêm mã này vào mã của bạn

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

và để thông tin.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>

NSLocationUsageDescriptionkhông được sử dụng trên iOS8 +
Carlos Ricardo

4

Để truy cập Vị trí người dùng trong iOS 8, bạn sẽ phải thêm,

NSLocationAlwaysUsageDescription in the Info.plist 

Điều này sẽ yêu cầu người dùng cho phép để có được vị trí hiện tại của họ.


4

Quy trình Mục tiêu-C Thực hiện theo các hướng dẫn bên dưới:

Đối với iOS-11 Đối với iOS 11, hãy xem Câu trả lời này:Truy cập vị trí iOS 11

Cần thêm hai khóa vào bảng và cung cấp thông báo như hình ảnh dưới đây:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

nhập mô tả hình ảnh ở đây Dành cho iOS-10 trở xuống:

NSLocationWhenInUseUsageDescription

nhập mô tả hình ảnh ở đây

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

Phương thức đại biểu

#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];
}

Thủ tục nhanh chóng

Thực hiện theo các hướng dẫn dưới đây:

Đối với iOS-11 Đối với iOS 11, hãy xem Câu trả lời: Truy cập vị trí iOS 11

Cần thêm hai khóa vào bảng và cung cấp thông báo như hình ảnh dưới đây:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

nhập mô tả hình ảnh ở đây Dành cho iOS-10 trở xuống:

nhập mô tả hình ảnh ở đây

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()
    }
}

Phương thức đại biểu

//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

}

Vui lòng đảm bảo NSLocationAlwaysUsageDes mô tả cũng được thêm vào nếu không bạn sẽ gặp lỗi trong khi tải lên trên cửa hàng ứng dụng.
Alok

Tin nhắn của bạn cũng nên được cung cấp thông tin nếu không apple sẽ từ chối ứng dụng trong khi quá trình cải tiến.
Alok

3

Đối với những người sử dụng Xamarin , tôi phải thêm khóa NSLocationWhenInUseUsageDescriptionvào info.plist bằng tay vì nó không có sẵn trong danh sách thả xuống trong Xamarin 5.5.3 Build 6 hoặc XCode 6.1 - chỉ có NSLocationUsageDescriptiontrong danh sách và điều đó khiến cho CLLocationManagerviệc tiếp tục thất bại âm thầm.


2
        // ** 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]);

}

2

Một người trợ giúp nhỏ cho tất cả các bạn có nhiều tệp Info.plist ...

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Add NSLocationWhenInUseUsageDescription string' {} 

Nó sẽ thêm thẻ cần thiết vào tất cả các tệp Info.plist trong thư mục hiện tại (và các thư mục con).

Cái khác là:

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Set NSLocationWhenInUseUsageDescription $YOURDESCRIPTION' {} 

Nó sẽ thêm mô tả của bạn vào tất cả các tập tin.



2

Tôi gặp một lỗi tương tự trong iOS9 (hoạt động với Xcode 7 và Swift 2): Đang cố gắng bắt đầu cập nhật vị trí MapKit mà không nhắc cấp phép vị trí. Phải gọi - [CLLocationManager requestWhenInUseAuthorization] hoặc - [CLLocationManager requestAlwaysAuthorization] trước tiên. Tôi đã làm theo hướng dẫn nhưng gia sư đang sử dụng iOS8 và Swift 1.2. Có một số thay đổi trong Xcode 7 và Swift 2, tôi đã tìm thấy mã này và nó hoạt động tốt với tôi (nếu ai đó cần trợ giúp):

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)
    }
}

Cuối cùng, tôi đặt nó trong info.plist: Danh sách tài sản thông tin: NSLocationWhenInUseUsageDescrip Giá trị: Ứng dụng cần máy chủ định vị cho nhân viên


2

Để truy cập vị trí người dùng trong iOS. Bạn cần thêm hai khóa

NSLocationWhenInUseUsage Mô tả

NSLocationAlwaysUsageDes mô tả

vào tệp 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>

Xem hình ảnh dưới đây.

Hình ảnh Info.plist


1
  1. Thêm khóa NSLocationWhenInUseUsageDescriptionhoặc NSLocationAlwaysUsageDescription(sử dụng GPS nền) với chuỗi yêu cầu sử dụng GPS trên info.plistmỗi mục tiêu.

  2. Xin phép bằng cách chạy:

    [tự initLocationManager: locationManager];

Ở đâu initLocationManager:

// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{

    locationManager = [[CLLocationManager alloc]init];

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

Hãy nhớ rằng nếu các phím không có trên info.plistmỗi mục tiêu thì ứng dụng sẽ không hỏi người dùng. Việc ifcung cấp khả năng tương thích với iOS 7 và respondsToSelector:phương pháp đảm bảo khả năng tương thích trong tương lai thay vì chỉ giải quyết vấn đề cho iOS 7 và 8.


0

Vấn đề đối với tôi là lớp học CLLocationManagerDelegatelà riêng tư, điều này ngăn cản tất cả các phương thức ủy nhiệm được gọi. Đoán nó không phải là một tình huống rất phổ biến nhưng nghĩ rằng tôi sẽ đề cập đến nó trong trường hợp t giúp đỡ bất cứ ai.


0

Tôi thêm những quan trọng trong InfoPlist.stringstrong iOS 8.4, iPad Mini 2. Nó hoạt động quá. Tôi không đặt bất kỳ khóa nào, như NSLocationWhenInUseUsageDescription, trong của tôi Info.plist.


InfoPlist.strings :

"NSLocationWhenInUseUsageDescription" = "I need GPS information....";

Dựa trên chủ đề này , nó nói as in iOS 7, có thể được bản địa hóa trong InfoPlist.strings. Trong thử nghiệm của tôi, các phím đó có thể được cấu hình trực tiếp trong tệp InfoPlist.strings.

Vì vậy, điều đầu tiên bạn cần làm là thêm một hoặc cả hai phím> sau vào tệp Info.plist của bạn:

  • NSLocationWhenInUseUsage Mô tả
  • NSLocationAlwaysUsageDes mô tả

Cả hai khóa này đều có một chuỗi mô tả lý do tại sao bạn cần dịch vụ định vị. Bạn có thể nhập một chuỗi như Vị trí của Bắt buộc để tìm ra vị trí của bạn, như trong iOS 7 , có thể được bản địa hóa trong tệp InfoPlist.strings.


CẬP NHẬT:

Tôi nghĩ rằng @IOSphương pháp của nó là tốt hơn. Thêm khóa vào Info.plistvới giá trị trống và thêm chuỗi địa phương vào InfoPlist.strings.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.