Mel*_*cuk 49 objective-c cllocationmanager ios
如何检查我的应用是否启用了位置服务?
我有2个故事板,我想检查位置服务.如果为我的应用启用了位置服务,我想启动带位置的地图故事板.否则,我想发布另一个故事板.我该如何以编程方式完成?
Mel*_*cuk 134
这是正确的.
if ([CLLocationManager locationServicesEnabled]){
NSLog(@"Location Services Enabled");
if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
alert = [[UIAlertView alloc] initWithTitle:@"App Permission Denied"
message:@"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
}
Run Code Online (Sandbox Code Playgroud)
swi*_*Boy 25
在iOS 9.2上测试过
要获取位置更新,我们应该始终检查
并在正确的设置屏幕上启动用户以启用
启动iOS设备位置设置页面
步骤1转到项目设置 - >信息 - > URL类型 - >添加新URL方案
Step.2使用以下代码启动直接电话的位置设置页面:(注意:iOS 10+中的URL方案不同,我们检查此处所述的版本)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice
currentDevice] systemVersion] compare:v options:NSNumericSearch] ==
NSOrderedAscending)
//Usage
NSString* url = SYSTEM_VERSION_LESS_THAN(@"10.0") ? @"prefs:root=LOCATION_SERVICES" : @"App-Prefs:root=Privacy&path=LOCATION";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];
Run Code Online (Sandbox Code Playgroud)
启动应用程序位置设置页面
使用以下代码启动直接应用程序的位置设置页面
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
Run Code Online (Sandbox Code Playgroud)
这是完整的代码示例:
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice
currentDevice] systemVersion] compare:v options:NSNumericSearch] ==
NSOrderedAscending)
CLLocationManager *locationManager;
-(void) checkLocationServicesAndStartUpdates
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[locationManager requestWhenInUseAuthorization];
}
//Checking authorization status
if (![CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Location Services Disabled!"
message:@"Please enable Location Based Services for better results! We promise to keep your location private"
delegate:self
cancelButtonTitle:@"Settings"
otherButtonTitles:@"Cancel", nil];
//TODO if user has not given permission to device
if (![CLLocationManager locationServicesEnabled])
{
alertView.tag = 100;
}
//TODO if user has not given permission to particular app
else
{
alertView.tag = 200;
}
[alertView show];
return;
}
else
{
//Location Services Enabled, let's start location updates
[locationManager startUpdatingLocation];
}
}
Run Code Online (Sandbox Code Playgroud)
处理用户单击响应,并启动正确的位置设置
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)//Settings button pressed
{
if (alertView.tag == 100)
{
//This will open ios devices location settings
NSString* url = SYSTEM_VERSION_LESS_THAN(@"10.0") ? @"prefs:root=LOCATION_SERVICES" : @"App-Prefs:root=Privacy&path=LOCATION";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];
}
else if (alertView.tag == 200)
{
//This will opne particular app location settings
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}
else if(buttonIndex == 1)//Cancel button pressed.
{
//TODO for cancel
}
}
Run Code Online (Sandbox Code Playgroud)
小智 21
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(@"%@",error.userInfo);
if([CLLocationManager locationServicesEnabled]){
NSLog(@"Location Services Enabled");
if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"App Permission Denied"
message:@"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
}
}
Run Code Online (Sandbox Code Playgroud)
这背后的原因,当您的服务将禁用位置服务时,此方法将调用.这段代码对我很有用.
Sum*_*dra 12
检查CLLocationManager的locationServicesEnabled属性以检查系统范围的可用性.使用您的CLLocationManagerDelegate的locationManager:didFailWithError:方法并检查kCLErrorDenied错误以查看用户是否拒绝了位置服务.
BOOL locationAllowed = [CLLocationManager locationServicesEnabled];
if (!locationAllowed)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location Service Disabled"
message:@"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
Run Code Online (Sandbox Code Playgroud)
为您的应用程序使用此代码
- (void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
locationManager.distanceFilter = 500;
[locationManager startUpdatingLocation];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// If it's a relatively recent event, turn off updates to save power
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"%@",error);
}
Run Code Online (Sandbox Code Playgroud)
如果位置服务禁用您的应用程序,那么它会给您错误
Error Domain=kCLErrorDomain Code=1 "The operation couldn’t be completed. (kCLErrorDomain error 1.)"
Run Code Online (Sandbox Code Playgroud)
has*_*san 11
经过大量调查.我建议在标签上显示此消息,而不是在警报视图上显示.因为,有很多情况需要测试(用户通常会禁用位置服务或只是为了删除应用程序,重新安装).
其中一种情况会导致您的警报同时显示您的消息以及Apple的警报消息.你的警报将落后苹果的警报.这是一种令人困惑和不合逻辑的行为.
我推荐以下内容:
斯威夫特3:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .notDetermined:
Log.verbose("User still thinking granting location access!")
manager.startUpdatingLocation() // this will access location automatically if user granted access manually. and will not show apple's request alert twice. (Tested)
break
case .denied:
Log.verbose("User denied location access request!!")
// show text on label
label.text = "To re-enable, please go to Settings and turn on Location Service for this app."
manager.stopUpdatingLocation()
loadingView.stopLoading()
break
case .authorizedWhenInUse:
// clear text
label.text = ""
manager.startUpdatingLocation() //Will update location immediately
break
case .authorizedAlways:
// clear text
label.text = ""
manager.startUpdatingLocation() //Will update location immediately
break
default:
break
}
}
Run Code Online (Sandbox Code Playgroud)
Objective-C的:
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
switch (status) {
case kCLAuthorizationStatusNotDetermined: {
DDLogVerbose(@"User still thinking granting location access!");
[locationManager startUpdatingLocation]; // this will access location automatically if user granted access manually. and will not show apple's request alert twice. (Tested)
} break;
case kCLAuthorizationStatusDenied: {
DDLogVerbose(@"User denied location access request!!");
// show text on label
label.text = @"To re-enable, please go to Settings and turn on Location Service for this app.";
[locationManager stopUpdatingLocation];
[loadingView stopLoading];
} break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways: {
// clear text
label.text = @"";
[locationManager startUpdatingLocation]; //Will update location immediately
} break;
default:
break;
}
}
Run Code Online (Sandbox Code Playgroud)
最好的办法,处理所有情况!->
//First, checking if the location services are enabled
if(![CLLocationManager locationServicesEnabled]){
[self showMessage:@"Please enable location services to detect location!" withTitle:@"Location not enabled"];
}
else if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
//Now if the location is denied.
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Enable location permission"
message:@"To auto detect location, please enable location services for this app"
preferredStyle:UIAlertControllerStyleAlert];
alertController.view.tintColor = AppColor;
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:@"Dismiss"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
NSLog(@"Cancel action");
}];
UIAlertAction *goToSettings = [UIAlertAction
actionWithTitle:@"Settings"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
//Simple way to open settings module
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url];
}];
[alertController addAction:cancelAction];
[alertController addAction:goToSettings];
[self presentViewController:alertController animated:YES completion:^{
alertController.view.tintColor = AppColor;
}];
}
else{
//Do whatever you want here
}
Run Code Online (Sandbox Code Playgroud)
在最新的 Swift 5.0、Xcode 11.2.1 中更新
import UIKit
import CoreLocation
Run Code Online (Sandbox Code Playgroud)
用户常量
struct UserConstants {
static let latitude = "latitude"
static let longitude = "longitude"
static let lastKnownLatitude = "lastKnownLatitude"
static let lastKnownLongitude = "lastKnownLongitude"
}
Run Code Online (Sandbox Code Playgroud)
Location Manager Delegate 用于监控位置变化
@objc protocol LocationManagerDelegate {
@objc optional func getLocation(location: CLLocation)
}
class LocationHelper: NSObject, CLLocationManagerDelegate {
weak var locationManagerDelegate: LocationManagerDelegate?
var isLocationfetched: Bool = false
var lastKnownLocation: CLLocation? {
get {
let latitude = UserDefaults.standard.double(forKey: UserConstants.lastKnownLatitude)
let longitude = UserDefaults.standard.double(forKey: UserConstants.lastKnownLongitude)
if latitude.isZero || longitude.isZero {
return nil
}
return CLLocation(latitude: latitude, longitude: longitude)
}
set {
UserDefaults.standard.set(newValue?.coordinate.latitude ?? 0, forKey: UserConstants.lastKnownLatitude)
UserDefaults.standard.set(newValue?.coordinate.longitude ?? 0, forKey: UserConstants.lastKnownLongitude)
UserDefaults.standard.synchronize()
}
}
struct SharedInstance {
static let instance = LocationHelper()
}
class var shared: LocationHelper {
return SharedInstance.instance
}
enum Request {
case requestWhenInUseAuthorization
case requestAlwaysAuthorization
}
var clLocationManager = CLLocationManager()
func setAccuracy(clLocationAccuracy: CLLocationAccuracy) {
clLocationManager.desiredAccuracy = clLocationAccuracy
}
var isLocationEnable: Bool = false {
didSet {
if !isLocationEnable {
lastKnownLocation = nil
}
}
}
Run Code Online (Sandbox Code Playgroud)
带有授权检查的位置更新
func startUpdatingLocation() {
isLocationfetched = false
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined:
clLocationManager.delegate = self
clLocationManager.requestWhenInUseAuthorization()
clLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
clLocationManager.startUpdatingLocation()
isLocationEnable = true
case .restricted, .denied:
showLocationAccessAlert()
isLocationEnable = false
case .authorizedAlways, .authorizedWhenInUse:
self.clLocationManager.delegate = self
self.clLocationManager.startUpdatingLocation()
isLocationEnable = true
default:
print("Invalid AuthorizationStatus")
}
} else {
isLocationEnable = false
showLocationAccessAlert()
}
}
Run Code Online (Sandbox Code Playgroud)
如果不允许,则显示位置警报
func showLocationAccessAlert() {
let alertController = UIAlertController(title: "Location Permission Required", message: "Please enable location permissions in settings.", preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "settings", style: .default, handler: {(cAlertAction) in
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
})
let cancelAction = UIAlertAction(title: "cancel", style: UIAlertAction.Style.cancel)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
let appdelegate = UIApplication.shared.delegate as? AppDelegate
appdelegate?.window?.rootViewController?.present(alertController, animated: true, completion: nil)
}
func stopUpdatingLocation() {
self.clLocationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if !isLocationfetched {
isLocationfetched = true
clLocationManager.startMonitoringSignificantLocationChanges()
NotificationCenter.default.post(name: NSNotification.Name.updateLocationNotification, object: nil)
}
let userLocation = locations[0] as CLLocation
self.lastKnownLocation = userLocation
if let delegate = self.locationManagerDelegate {
delegate.getLocation!(location: userLocation)
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.denied) {
// The user denied authorization
isLocationEnable = false
} else if (status == CLAuthorizationStatus.authorizedWhenInUse) {
// The user accepted authorization
self.clLocationManager.delegate = self
self.clLocationManager.startUpdatingLocation()
isLocationEnable = true
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("\n error description for location updation:- \(error.localizedDescription)")
}
}
Run Code Online (Sandbox Code Playgroud)
对于上面的测试,只需在控制器中编写这些代码行,
LocationHelper.shared.locationManagerDelegate = self
LocationHelper.shared.startUpdatingLocation()
Run Code Online (Sandbox Code Playgroud)
LocationManagerDelegate 方法
extension ViewController: LocationManagerDelegate {
func getLocation(location: CLLocation) {
currentLocation = location.coordinate
}
}
Run Code Online (Sandbox Code Playgroud)