我在iOS 7上运行良好的应用无法与iOS 8 SDK配合使用。
CLLocationManager
未返回位置,我在设置 - >>下看不到我的应用位置服务。我在这个问题上进行了谷歌搜索,但没有出现任何问题。可能有什么不对?
答案 0 :(得分:1085)
我最终解决了自己的问题。
显然在iOS 8 SDK中,在开始位置更新之前需要requestAlwaysAuthorization
(用于后台位置)或requestWhenInUseAuthorization
(仅在前景时的位置)调用CLLocationManager
。
NSLocationAlwaysUsageDescription
中还需要NSLocationWhenInUseUsageDescription
或Info.plist
键,并在提示中显示消息。添加这些解决了我的问题。
希望它可以帮助别人。
编辑:有关更多信息,请查看:Core-Location-Manager-Changes-in-ios-8
答案 1 :(得分:312)
我正在把头发拉出来同样的问题。 Xcode为您提供错误:
尝试在不提示的情况下启动
MapKit
位置更新 位置授权。必须先致电-[CLLocationManager requestWhenInUseAuthorization]
或-[CLLocationManager requestAlwaysAuthorization]
。
但即使您实施上述方法之一,它也不会提示用户,除非{。1}}或NSLocationAlwaysUsageDescription
的info.plist中有条目。
将以下行添加到info.plist,其中字符串值表示您需要访问用户位置的原因
NSLocationWhenInUseUsageDescription
我认为自从我在Xcode 5中启动此项目后,这些条目可能已经丢失。我猜测Xcode 6可能会为这些密钥添加默认条目但尚未确认。
您可以在这两个设置here
上找到更多相关信息答案 2 :(得分:104)
为确保向后兼容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];
答案 3 :(得分: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
}
以及您的info.plist文件
答案 4 :(得分:30)
根据Apple文档:
从iOS 8开始,您需要在应用的Info.plist文件中显示NSLocationWhenInUseUsageDescription
或NSLocationAlwaysUsageDescription
键值。然后,在注册位置更新之前,还需要通过根据您的需要致电[self.myLocationManager requestWhenInUseAuthorization]
或[self.myLocationManager requestAlwaysAuthorization]
来请求用户的许可。您输入Info.plist的字符串将显示在随后的对话框中。
如果用户授予权限,则照常营业。如果他们拒绝许可,则代理人不会被告知位置更新。
答案 5 :(得分: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];
}
}
在iOS 8中,您需要做两件额外的事情才能让位置正常工作:添加 Info.plist的一个键,并从该位置请求授权 经理要求它开始。新的有两个Info.plist键 位置授权。需要这些键中的一个或两个。如果 这两个键都没有,你可以调用startUpdatingLocation但是 位置管理员实际上不会启动。它不会发送失败 消息给代表(因为它从未开始,它不能 失败)。如果你添加一个或两个键但忘记它也会失败 明确请求授权。所以你需要做的第一件事 是将以下一个或两个键添加到Info.plist文件中:
这两个键都带有一个字符串
描述了您需要位置服务的原因。您可以 输入一个字符串,如“需要位置才能找到你所在的位置” 这与iOS 7一样,可以在InfoPlist.strings文件中进行本地化。
答案 6 :(得分:19)
我的解决方案可以在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];
答案 7 :(得分:17)
询问位置的旧代码在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];
}
}
答案 8 :(得分:12)
在iOS 8中,您需要做两件额外的事情才能让位置正常工作:在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];
}
答案 9 :(得分:11)
Swift开发人员的一个常见错误:
首先确保为NSLocationWhenInUseUsageDescription
或NSLocationAlwaysUsageDescription
的plist添加值。
如果您仍然没有看到弹出要求授权的窗口,请查看您是否将行var locationManager = CLLocationManager()
放入View Controller的viewDidLoad
} 方法。如果您这样做,那么即使您致电locationManager.requestWhenInUseAuthorization()
,也不会显示任何内容。这是因为在viewDidLoad执行之后,将取消分配(清除)locationManager变量。
解决方案是将行var locationManager = CLLocationManager()
定位在类方法的顶部。
答案 10 :(得分:9)
在[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
。
答案 11 :(得分:9)
我正在开发一款升级到iOS 8且位置服务停止运行的应用。您可能会在调试区域中得到错误,如下所示:
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
我做了最少侵入性的程序。首先将NSLocationAlwaysUsageDescription
条目添加到info.plist:
注意我没有填写此密钥的值。这仍然有效,我并不担心,因为这是一个内部应用程序。此外,已经有一个标题要求使用位置服务,所以我不想做任何多余的事情。
接下来,我为iOS 8创建了一个条件:
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_locationManager requestAlwaysAuthorization];
}
此后调用locationManager:didChangeAuthorizationStatus:
方法:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus: (CLAuthorizationStatus)status
{
[self gotoCurrenLocation];
}
现在一切正常。与往常一样,请查看documentation。
答案 12 :(得分:7)
具有向后兼容性的解决方案:
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键
答案 13 :(得分:6)
具有向后兼容性且不会产生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];
}
在NSLocationWhenInUseUsageDescription
中设置Info.plist
密钥。
适用于iOS版本11.0 + :
在NSLocationAlwaysAndWhenInUseUsageDescription
设置Info.plist
密钥。以及其他2个键。
答案 14 :(得分:5)
这是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>
答案 15 :(得分:4)
Objective-C程序 请按照以下说明操作:
适用于iOS-11 对于iOS 11,请查看此答案:iOS 11 location access
需要在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 location access
需要在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
}
答案 16 :(得分:4)
要在iOS 8中访问用户位置,您必须添加
NSLocationAlwaysUsageDescription in the Info.plist
这将要求用户获得获取当前位置的权限。
答案 17 :(得分:3)
对于使用 Xamarin 的用户,我必须手动将密钥 NSLocationWhenInUseUsageDescription
添加到info.plist中,因为它在Xamarin的下拉列表中不可用5.5.3 Build 6或XCode 6.1 - 列表中只有NSLocationUsageDescription
,导致CLLocationManager
继续无声地失败。
答案 18 :(得分: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]);
}
答案 19 :(得分:2)
保持 Cocoa Keys 信息随时可以获取这些更新,以下是链接:
享受。
答案 20 :(得分:2)
我在iOS9中遇到类似的错误(使用Xcode 7和Swift 2): 尝试在不提示位置授权的情况下启动MapKit位置更新。必须先调用 - [CLLocationManager requestWhenInUseAuthorization]或 - [CLLocationManager requestAlwaysAuthorization]。 我正在学习一个教程,但导师使用的是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 价值:应用需要员工的位置服务器
答案 21 :(得分:2)
为了访问iOS中的用户位置。您需要添加两个键
<强> 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>
见下图。
答案 22 :(得分:2)
为所有拥有多个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' {}
它会将您的描述添加到所有文件中。
答案 23 :(得分:1)
添加密钥NSLocationWhenInUseUsageDescription
或NSLocationAlwaysUsageDescription
(使用后台GPS),并在每个目标的每个info.plist
上使用字符串。
通过运行来获取许可:
[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的问题。
答案 24 :(得分:0)
对我来说问题是CLLocationManagerDelegate
的类是私有的,它阻止了所有委托方法的调用。猜猜这不是一个非常普遍的情况,但我想如果t帮助任何人我会提到它。
答案 25 :(得分:0)
我在 iOS 8.4,iPad mini 2中的InfoPlist.strings
中添加了这些密钥。它也有效。我没有在NSLocationWhenInUseUsageDescription
中设置任何密钥,例如Info.plist
。
InfoPlist.strings :
"NSLocationWhenInUseUsageDescription" = "I need GPS information....";
Base on this thread,它说,as in iOS 7
,可以在InfoPlist.strings中进行本地化。在我的测试中,可以直接在文件InfoPlist.strings
中配置这些密钥。
所以你需要做的第一件事就是添加一个或两个&gt;以下密钥到您的Info.plist文件:
- NSLocationWhenInUseUsageDescription
- NSLocationAlwaysUsageDescription
这两个键都带有一个字符串,它描述了你的原因 需要位置服务。您可以输入“位置为”等字符串 需要找出你的位置“,如 iOS 7 ,可以 本地化在InfoPlist.strings文件中。
<强>更新强>
我认为@IOS
's method is better.使用空值为Info.plist
添加密钥,并将本地化字符串添加到InfoPlist.strings
。