我在 iOS 7 上运行良好的应用程序不适用于 iOS 8 SDK。
CLLocationManager
不返回位置,我也没有在“设置” -> “位置服务”下看到我的应用程序。我对这个问题进行了谷歌搜索,但没有任何结果。有什么问题?
我在 iOS 7 上运行良好的应用程序不适用于 iOS 8 SDK。
CLLocationManager
不返回位置,我也没有在“设置” -> “位置服务”下看到我的应用程序。我对这个问题进行了谷歌搜索,但没有任何结果。有什么问题?
我最终解决了我自己的问题。
显然在 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
or的条目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 中开始这个项目以来,这些条目可能已经丢失。我猜 Xcode 6 可能会为这些键添加默认条目,但尚未确认。
您可以在此处找到有关这两个设置的更多信息
为确保向后兼容 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 文件中需要存在 aNSLocationWhenInUseUsageDescription
或NSLocationAlwaysUsageDescription
key 值。然后还需要在注册位置更新之前请求用户的许可,无论是通过电话[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 中,您需要做两件额外的事情才能让定位工作:将密钥添加到您的 Info.plist 并从定位管理器请求授权以启动它。新的位置授权有两个 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 中,你需要做两件额外的事情来让位置工作:向你的 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
或向 plist 添加一个值NSLocationAlwaysUsageDescription
。
如果您仍然没有看到弹出请求授权的窗口,请查看您是否将该行var locationManager = CLLocationManager()
放入 View Controller 的viewDidLoad
方法中。如果你这样做了,那么即使你打电话locationManager.requestWhenInUseAuthorization()
,也不会出现任何东西。这是因为 viewDidLoad 执行后,locationManager 变量被释放(清除)。
解决方案是将行定位var locationManager = CLLocationManager()
在类方法的顶部。
我正在开发一个升级到 iOS 8 的应用程序并且位置服务停止工作。您可能会在 Debug 区域中出现错误,如下所示:
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];
}
现在一切正常。与往常一样,请查看文档。
在之前[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
.
向后兼容的解决方案:
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];
}
您NSLocationWhenInUseUsageDescription
的Info.plist
.
对于 iOS 版本 11.0+:NSLocationAlwaysAndWhenInUseUsageDescription
您的Info.plist
. 连同其他 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 位置访问
需要在 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 位置访问
需要在 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的人,我必须NSLocationWhenInUseUsageDescription
手动将密钥添加到 info.plist,因为它在 Xamarin 5.5.3 Build 6 或 XCode 6.1 的下拉列表中不可用 - 仅 NSLocationUsageDescription
在列表中,这导致CLLocationManager
继续默默地失败。
// ** 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 文件的所有人来说,这是一个小帮手...
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' {}
它会将您的描述添加到所有文件中。
让Cocoa Keys信息始终触手可及,以获取这些更新,这里是链接:
享受。
我在 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 值:应用程序需要员工的位置服务器
为了访问用户在 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>
请参见下图。
添加键NSLocationWhenInUseUsageDescription
或NSLocationAlwaysUsageDescription
(背景 GPS 使用)和字符串,要求在info.plist
每个目标上使用 GPS。
通过运行请求许可:
[自我 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
是私有的,这阻止了所有委托方法被调用。猜猜这不是一个很常见的情况,但我想我会提到它以防万一帮助任何人。
InfoPlist.strings
我在iOS 8.4、iPad mini 2中添加了这些键。它也可以。我没有NSLocationWhenInUseUsageDescription
在我的Info.plist
.
InfoPlist.strings:
"NSLocationWhenInUseUsageDescription" = "I need GPS information....";
它说,基于这个线程as in iOS 7
,可以在 InfoPlist.strings 中进行本地化。在我的测试中,这些键可以直接在文件中配置InfoPlist.strings
。
因此,您需要做的第一件事是将 > 以下键中的一个或两个添加到 Info.plist 文件中:
- NSLocationWhenInUseUsageDescription
- NSLocationAlwaysUsageDescription
这两个键都带有一个字符串,该字符串描述了您需要位置服务的原因。您可以输入一个字符串,如“Location is required to find out you are”,就像在iOS 7中一样,可以在 InfoPlist.strings 文件中进行本地化。
更新:
我认为@IOS
's 的方法更好。添加Info.plist
具有空值的键并将本地化字符串添加到InfoPlist.strings
.