位置服务在 iOS 8中无法使用

My app that worked fine on iOS 7 doesn't work with the iOS 8 SDK.

CLLocationManager doesn't return a location, and I don't see my app under Settings -> Location Services either. I did a Google search on the issue, but nothing came up. What could be wrong?

转载于:https://stackoverflow.com/questions/24062509/location-services-not-working-in-ios-8

weixin_41568126
乱世@小熊 You can refer this link : iOS: Core Location is not asking user's permission
4 年多之前 回复
csdnceshi65
larry*wei You sir! need a crown! I have been fighting with this problem since change and have yet to find an "guide" how to fix it, that was noob friendly.. Your guide made an idiot like me, handle the problem my self. Thank you so much for that link.
5 年多之前 回复
csdnceshi71
Memor.の you can refer this post with stackoverflow.com/questions/25911330/…
接近 6 年之前 回复
weixin_41568184
叼花硬汉 I found some reference here datacalculation.blogspot.in/2014/11/…
接近 6 年之前 回复
csdnceshi74
7*4 You could try using this library which simplifies the Core Location APIs and exposes a nice blocks based interface, and normalises all the differences between different iOS versions (Full disclosure: I'm the author): github.com/lmirosevic/GBLocation
接近 6 年之前 回复
weixin_41568110
七度&光 I posted about some of the changes to the location manager in iOS 8 here: nevan.net/2014/09/core-location-manager-changes-in-ios-8
接近 6 年之前 回复
csdnceshi72
谁还没个明天 You can also use this as reference app for the solution github.com/jbanford/ConstantLocationUpdates
大约 6 年之前 回复

26个回答

I ended up solving my own problem.

Apparently in iOS 8 SDK, requestAlwaysAuthorization (for background location) or requestWhenInUseAuthorization (location only when foreground) call on CLLocationManager is needed before starting location updates.

There also needs to be NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in Info.plist with a message to be displayed in the prompt. Adding these solved my problem.

enter image description here

Hope it helps someone else.

EDIT: For more extensive information, have a look at: Core-Location-Manager-Changes-in-ios-8

csdnceshi58
Didn"t forge Wow, thanks for the help. I couldn't figure this out. Apple, if you read this stuff, please do a better job of documenting
5 年多之前 回复
csdnceshi54
hurriedly% For what it's worth, the key needs to go in the applications plist, even if the location manager code is in a framework.
5 年多之前 回复
csdnceshi52
妄徒之命 I had a legacy MyApp.plist that I was updating (from XCode 4 or something) and after many hours figured that I needed to select my target (of which I had 2) then Info -> Custom iOS Target Properties and add in the new strings there, once for each target. What a faff !
5 年多之前 回复
csdnceshi62
csdnceshi62 Location monitoring is a very complexed subject when balance between battery consumption and 'always-on' accuracy is so important. Here's a great SDK that does it all for you: github.com/IngeoSDK/ingeo-ios-sdk
5 年多之前 回复
csdnceshi60
℡Wang Yan ty very much! works like a charm
5 年多之前 回复
weixin_41568127
?yb? It's 3:18 in the morning. Many thanks to @OrtwinGentz for my remaining couple hours of sleep!!
5 年多之前 回复
csdnceshi73
喵-见缝插针 The link in your answer really explains it well
5 年多之前 回复
weixin_41568126
乱世@小熊 HOURS AND HOURS of research!!! This finally was the solution!
接近 6 年之前 回复
csdnceshi59
ℙℕℤℝ I wish I'm able to vote you up more than one time
接近 6 年之前 回复
csdnceshi75
衫裤跑路 my comment is obsolete now since iOS 8 is out. Before it was out, one could not use the requestAlwaysAuthorization selector because it was only available in the Beta SDK and builds against a Beta SDK aren't accepted in the App Store review.
接近 6 年之前 回复
csdnceshi56
lrony* this solution worked for me with my deployment target set to 7.0. Without it, the 8.0 devices were failing to get location services. Is this what you mean? Has something changed since you first posted?
接近 6 年之前 回复
csdnceshi76
斗士狗 D'oh! Figured it out...I was using quick-open to jump to the plist, and it was the plist for a framework I'm using rather than for the app itself. That was stupid.
接近 6 年之前 回复
csdnceshi76
斗士狗 Even more weirdness ensues...when I allow location services for my app manually in settings, on launch my auth status shows as "authorized". Then I immediately get a notification that it has changed to "not determined". Better yet, when I click back to settings, my change is undone! What the hell???
接近 6 年之前 回复
csdnceshi76
斗士狗 I did both of these things and still no dice...user never gets prompted, even on a fresh install. I even went into settings and enabled location services manually for my app, and STILL do not get any location updates, and the auth status is always "not determined". I'm rather frustrated with Apple for screwing with this and breaking a lot of perfectly good code. But, such is life.
接近 6 年之前 回复
weixin_41568183
零零乙 If the messages for NSLocationWhenInUseUsageDescription are showing up in the UI, how can we localise it?
接近 6 年之前 回复
csdnceshi79
python小菜 Thanks for this solution. It worked here! Cheers
接近 6 年之前 回复
csdnceshi78
程序go Here is the relevant PDF from WWDC 2014 that describes the changes that developers need to implement (pp 108 and 116): devstreaming.apple.com/videos/wwdc/2014/706xxjytntg51wd/706/…
接近 6 年之前 回复
weixin_41568208
北城已荒凉 I found that I had to add both keys regardless of which auth I called to CLLocationManager.
接近 6 年之前 回复
csdnceshi69
YaoRaoLov I 'LOVE' that you get no error, no warning, no log message, NOTHING if you leave out the plist entry. Basically Apple has created an API call that does NOTHING if you don't have the appropriate plist entry. Thanks to @OrtwinGentz for figuring this out.
接近 6 年之前 回复
csdnceshi74
7*4 You need to retain your locationManager to make it work. so make your CLLocationManager as a strong property
接近 6 年之前 回复
csdnceshi65
larry*wei why is that? You're right, it works for me to edit Info.plist but not if set in Xcode.
大约 6 年之前 回复
csdnceshi67
bug^君 How can I localize it ?
大约 6 年之前 回复
csdnceshi50
三生石@ Just a reminder, if you don't wanna show custom explanation to the user, just set this key to an empty string.
大约 6 年之前 回复
csdnceshi51
旧行李 Hey its not working in my case :( Please help me to modify Info.Plist by using NSLocationWhenInUseUsageDescription ...
大约 6 年之前 回复
weixin_41568184
叼花硬汉 - you have to edit the Info.plist file in an editor, cannot set those keys in Xcode (as of beta 6).
大约 6 年之前 回复
weixin_41568134
MAO-EYE Nice one! Additional "gotcha": although iOS 8 docs say that didChangeAuthorizationStatus will only get called for changes, that's not true. For me in iOS 8 beta 5 on an iP5, it gets called multiple times, first with status kCéAuthorizationStatusNotDetermined, which is odd.
大约 6 年之前 回复
csdnceshi61
derek5. can you share the exact valur u updated in Info.plist? Iam not able to see that key in my Info.plist. I added it and still it does not seem to work. I am using Swift, iOS8 and XCode 6 beta 4
大约 6 年之前 回复
csdnceshi68
local-host So if I use MapKit, i will have to us CLLocation to make the request?
大约 6 年之前 回复
csdnceshi75
衫裤跑路 This is of course not a solution for apps built against the iOS 7 SDK as required for submitting to the App Store now. I've filed rdar://17465666: openradar.appspot.com/17465666
大约 6 年之前 回复

To ensure that this is backwards compatible with iOS 7, you should check whether the user is running iOS 8 or iOS 7. For example:

#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];
weixin_41568174
from.. You have to call '[self.locationManager startUpdatingLocation];' when the user have accepted / rejected the authorization. This is my code: - (void) locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{ if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) { [_locationManager startUpdatingLocation]; } }
4 年多之前 回复
csdnceshi62
csdnceshi62 for the life of me i cannot get this to work. It works great on iOS 8 (with the call for requestAlwaysAuthorization) but as soon as i put in the IF statement to check iOS version, it stops working on iOS8 and the prompt to allow to use location flashes and immediately disappears and I don't get my location. Anyone have any ideas why? its driving me insane!
接近 6 年之前 回复
csdnceshi76
斗士狗 Don't forget to set the delegate for the location manager and allocate it: _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; stackoverflow.com/questions/24717547/… has a the complete code if you're still stuck
接近 6 年之前 回复
csdnceshi73
喵-见缝插针 the recommended approach is to conditionally compile using the SDK defined macro __IPHONE_OS_VERSION_MAX_ALLOWED (#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
接近 6 年之前 回复
csdnceshi59
ℙℕℤℝ thanks for you too.
大约 6 年之前 回复
csdnceshi59
ℙℕℤℝ thanks for the clean solution.
大约 6 年之前 回复
csdnceshi51
旧行李 You might have a point. My concern was that I wanted my code to compile in Xcode 5 (even though it won't work on iOS 8 unless compiled in Xcode 6) while my team transitions to Xcode 6. But maybe it's a better workflow to write the code normally and not merge it in until we move to Xcode 6.. Thanks.
大约 6 年之前 回复
csdnceshi61
derek5. The right solution is to build with Xcode 6. If you are building with Xcode 5 you don't need to request authorization, it's automatic.
大约 6 年之前 回复
csdnceshi51
旧行李 I had trouble just implementing @progrmr's solution when building on Xcode 5, since it doesn't know what the requestAlwaysAuthorization method is. My additional solution was to use this line in the if statement instead of a normal method call: [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. Maybe this is obvious to other people, but it took me a while to figure out. I think it's the right solution until the final Xcode 6 is released.
大约 6 年之前 回复
csdnceshi77
狐狸.fox Awesome, thanks! I never knew that, thats a much cleaner solution it seems.
大约 6 年之前 回复
csdnceshi61
derek5. A better way than checking version is to check to see if the object has that selector, e.g.: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
大约 6 年之前 回复

I was pulling my hair out with the same problem. Xcode gives you the error:

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

But even if you implement one of the above methods, it won't prompt the user unless there is an entry in the info.plist for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription.

Add the following lines to your info.plist where the string values represent the reason you you need to access the users location

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

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

I think these entries may have been missing since I started this project in Xcode 5. I'm guessing Xcode 6 might add default entries for these keys but have not confirmed.

You can find more information on these two Settings here

csdnceshi74
7*4 Thank you. Its working good.
3 年多之前 回复
csdnceshi52
妄徒之命 You saved me a tonne of time. Thank you.
5 年多之前 回复
csdnceshi70
笑故挽风 Apple you FAILED! Why not have it default to a generic message? Why not give some type of error when trying to use location manager without this plist key?
接近 6 年之前 回复
csdnceshi58
Didn"t forge Thanks for the example!!! This worked!
接近 6 年之前 回复
csdnceshi71
Memor.の Awesome. Thank you very much.
接近 6 年之前 回复
csdnceshi59
ℙℕℤℝ The message will appear as the sub-message in the Alert that asks whether the user would like to share their location. As such, simply being empty (blank) seems to make the most sense in my application. An explanation of why you want to use location would also make sense. However, NSLocationWhenInUseUsageDescription did not behave as expected for me (ie. kept getting permission denied, even though the return value was correct). NSLocationAlwaysUsageDescription worked fine.
接近 6 年之前 回复
weixin_41568183
零零乙 Stupid question: what is a good message here? And how to localize it?
大约 6 年之前 回复
weixin_41568174
from.. One question, how can I localized this message ?
大约 6 年之前 回复
csdnceshi76
斗士狗 I like the string value you put in
大约 6 年之前 回复
csdnceshi68
local-host I was able to add the keys in the Xcode 6 GM, though there's no long-string version. Works!
大约 6 年之前 回复
csdnceshi79
python小菜 i looked forever for this. My [CLLLocationManager authorizationStatus] message was only returning a value of <nil>. After adding the above keys it started returning the respective enumerations for the messages' output. From what ive found this is a known iOS 8 bug but couldnt find anything in my context for ages. Thanks a mil!
大约 6 年之前 回复
csdnceshi80
胖鸭 I also had to add these manually, could not add through the RawValues view of info.plist in Xcode6!
大约 6 年之前 回复
csdnceshi73
喵-见缝插针 At least one of those keys are required to use location in iOS 8.
6 年多之前 回复
csdnceshi69
YaoRaoLov xcode 6 does not add these keys by default, if you intend to implement CLLocationManager you must add them manually
6 年多之前 回复

According to the Apple docs:

As of iOS 8, the presence of a NSLocationWhenInUseUsageDescription or a NSLocationAlwaysUsageDescription key value in your app's Info.plist file is required. It's then also necessary to request permission from the user prior to registering for location updates, either by calling [self.myLocationManager requestWhenInUseAuthorization] or [self.myLocationManager requestAlwaysAuthorization] depending on your need. The string you entered into the Info.plist will then be displayed in the ensuing dialog.

If the user grants permission, it's business as usual. If they deny permission, then the delegate is not informed of location updates.

csdnceshi76
斗士狗 I found simple description here at datacalculation.blogspot.in/2014/11/…
接近 6 年之前 回复

For those using Xamarin, I had to add the key NSLocationWhenInUseUsageDescription to the info.plist manually since it was not available in the dropdowns in either Xamarin 5.5.3 Build 6 or XCode 6.1 - only NSLocationUsageDescription was in the list, and that caused the CLLocationManager to continue to fail silently.

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

}

A little helper for all of you that have more than one Info.plist file...

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

It will add the needed tag to all of the Info.plist files in the current directory (and subfolders).

Another is:

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

It will add your description to all files.

One common error for Swift developers:

First make sure you add a value to the plist for either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription.

If you are still not seeing a window pop up asking for authorization, look to see if you are putting the line var locationManager = CLLocationManager() in your View Controller's viewDidLoad method. If you do, then even if you call locationManager.requestWhenInUseAuthorization(), nothing will show up. This is because after viewDidLoad executes, the locationManager variable is deallocated (cleared out).

The solution is to locate the line var locationManager = CLLocationManager() at the top of the class method.

csdnceshi56
lrony* Thanks, you saved me a lot of headache!
4 年多之前 回复

This is issue with ios 8 Add this to your code

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

and to 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>
csdnceshi63
elliott.david NSLocationUsageDescription is not used on iOS8+
3 年多之前 回复

Objective-C Procedure Follow the below instructions:

For iOS-11 For iOS 11 have a look at this Answer: iOS 11 location access

Need to Add two Keys into plist and provide message as below image:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

enter image description here For iOS-10 and below:

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

Delegate Methods

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

Swift Procedure

Follow the below instructions:

For iOS-11 For iOS 11 have a look at this Answer: iOS 11 location access

Need to Add two Keys into plist and provide message as below image:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

enter image description here For iOS-10 and below:

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

Delegate Methods

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

}
csdnceshi68
local-host Your message should also be informative otherwise apple will reject the app while reviwing process.
2 年多之前 回复
csdnceshi68
local-host Please make sure NSLocationAlwaysUsageDescription is also added otherwise you will get an error while uploading on the app store.
2 年多之前 回复
共26条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐