一、定位属于用户的隐私,iOS8.0之后获取定位需向用户进行授权
授权方式:
1.1、前台授权,info.plist文件里设置字典“NSLocationWhenInUseUsageDescription”
注意:若前台授权的状态下,想获取后台定位,需勾选后台模式,如图
1.2、前后台授权,
在info.plist文件中配置字典NSLocationAlwaysUsageDescription,
如图:
1.3、若在info.plist中前后台授权和前台授权都有配置,则用请求权限比较高的那个,即前后台授权
1.4、授权之后、设置代理,完成相应的代理方法即可
二、相关的代码
2.1、OC代码:
调用:
#import "ViewController.h"
#import "SHLocationTool.h"
@implementation ViewController
- (IBAction)clickBtn:(id)sender {
[[SHLocationTool shareInstance]getCurrentLocationWithOnce:NO andResultBlock:^(CLLocation *location, NSString *errorMsg) {
if (!errorMsg) {
NSLog(@"latitude,%lf longitude,%lf errorMsg,%@",location.coordinate.latitude,location.coordinate.longitude,errorMsg);
}else {
NSLog(@"latitude,%lf longitude,%lf errorMsg,%@",location.coordinate.latitude,location.coordinate.longitude,errorMsg);
}
}];
}
代码实现:
//
// SHLocationTool.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
typedef void(^ResultBlock)(CLLocation *location,NSString *errorMsg);
@interface SHLocationTool : NSObject
+ (instancetype)shareInstance;
- (void)getCurrentLocationWithOnce:(BOOL)isOnce andResultBlock:(ResultBlock)resultBlock;
@end
#import "SHLocationTool.h"
#import <UIKit/UIKit.h>
#define kSystemVersion [UIDevice currentDevice].systemVersion
#define kIsVersion8 [kSystemVersion floatValue] >= 8.0
#define kIsVersion9 [kSystemVersion floatValue] >= 9.0
@interface SHLocationTool ()<CLLocationManagerDelegate>
@property (nonatomic, strong) CLLocationManager *locationM;//位置管理者
@property (nonatomic, copy) ResultBlock resultBlock;//结果block
@property (nonatomic, assign) BOOL isOnce;//是获取一次还是始终获取
@end
@implementation SHLocationTool
static SHLocationTool *_locationTool;
+ (instancetype)shareInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_locationTool = [[SHLocationTool alloc]init];
});
return _locationTool;
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
CLLocation *loc = locations.lastObject;
if (!loc && self.resultBlock) {
self.resultBlock(nil,@"没有获取到位置信息");
return;
}
self.resultBlock(loc,nil);
if (self.isOnce) {
[manager stopUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusDenied:
self.resultBlock(nil,@"当前被拒绝");
break;
case kCLAuthorizationStatusRestricted:
self.resultBlock(nil,@"当前受限制");
break;
case kCLAuthorizationStatusNotDetermined:
self.resultBlock(nil,@"用户没决定哈哈哈哈哈哈");
break;
default:
break;
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
[manager startUpdatingLocation];
}
#pragma mark - Public Methods
- (void)getCurrentLocationWithOnce:(BOOL)isOnce andResultBlock:(ResultBlock)resultBlock
{
self.resultBlock = resultBlock;
self.isOnce = isOnce;
if ([CLLocationManager locationServicesEnabled]) {
[self.locationM startUpdatingLocation];
}else {
if (self.resultBlock) {
self.resultBlock(nil,@"没有开启定位服务");
}
}
}
#pragma mark - Getters
- (CLLocationManager *)locationM
{
if (!_locationM) {
_locationM = [[CLLocationManager alloc]init];
_locationM.delegate = self;
// 强求授权
// 版本判断
if (kIsVersion8) {
//请求前后台定位授权
//请求前台定位授权
//1、获取info.plist文件的内容
NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
if (!infoDic) {
return _locationM;
}
//2、获取前台定位授权的key 值
NSString *whenInUse = infoDic[@"NSLocationWhenInUseUsageDescription"];
//3、获取前后台定位授权的key 值
NSString *always = infoDic[@"NSLocationAlwaysUsageDescription"];
//4、如果两个都有,用请求权限比较高的那个
if (always != nil) {
[_locationM requestAlwaysAuthorization];
}else if (whenInUse != nil) {
[_locationM requestWhenInUseAuthorization];
//1、判断后台模式有没有勾选location updates
//2、判断当前版本是否是iOS9.0,只有在iOS9.0之后才需要额外设置一个属性为ture
NSArray *backModes = infoDic[@"UIBackgroundModes"];
NSLog(@"%@",kSystemVersion);
if (backModes != nil && [backModes containsObject:@"location"] && kIsVersion9) {
_locationM.allowsBackgroundLocationUpdates = YES;
}
}else {
NSLog(@"请在info.plist进行相关的配置");
}
}
}
return _locationM;
}
@end
2.2、Swift代码:
调用:
import UIKit
class ViewController: UIViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
SHLocationTool.shareInstance.getCurrentLocation(isOnce: false) { (loc, errorMsg) -> () in
if errorMsg == nil {
print(loc)
}
}
}
}
代码实现:
import UIKit
import Foundation
import CoreLocation
typealias LocationResultBlock = (_:CLLocation?,_:String?) -> ()
class SHLocationTool: NSObject {
var isOnce:Bool = false
static let shareInstance = SHLocationTool()
lazy var locationM: CLLocationManager = {
// 创建定位管理者
let locationM = CLLocationManager()
// 设置代理
locationM.delegate = self
if #available(iOS 8.0, *) {
/*
1、取info.plist中的键值对
2、查看有没有设置键:
2.1、NSLocationAlwaysUsageDescription,用于前后台授权
2.2、NSLocationWhenInUseUsageDescription,用于前台授权
注意:iOS9.0之后需设置allowsBackgroundLocationUpdates属性值为ture,才具有后台授权的功能
*/
// 1. 获取info.plist文件内容
guard let infoDic = Bundle.main.infoDictionary else {return locationM}
// 2. 获取前台定位授权的key 值
let whenInUse = infoDic["NSLocationWhenInUseUsageDescription"]
// 3. 获取前后台定位授权key 值
let always = infoDic["NSLocationAlwaysUsageDescription"]
// 4. 判断: 如果两个都有, 请求权限比较高的哪一个
// 如果只有某一个, 那就请求对应的授权
// 如果两个都没有, 给其他开发者提醒
if always != nil {
locationM.requestAlwaysAuthorization()
}else if whenInUse != nil {
locationM.requestWhenInUseAuthorization()
// 1. 判断后台模式有没有勾选location updates
// 2. 判断当前版本时候是ios9.0, 因为只有在ios9.0以后, 才需要额外的设置一个属性为true
let backModes = infoDic["UIBackgroundModes"]
if backModes != nil {
let resultBackModel = backModes as! [String]
if resultBackModel.contains("location") {
if #available(iOS 9.0, *) {
locationM.allowsBackgroundLocationUpdates = true
}
}
}
}else {
print("在info.plist中配置")
}
}
return locationM
}()
var resultBlock: LocationResultBlock?
func getCurrentLocation(isOnce:Bool, resultBlock: @escaping LocationResultBlock) -> () {
self.isOnce = isOnce
self.resultBlock = resultBlock
if CLLocationManager.locationServicesEnabled() {
locationM.startUpdatingLocation()
}else {
if self.resultBlock != nil {
self.resultBlock!(nil,"当前没有开启定位服务")
}
}
}
}
extension SHLocationTool:CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard locations.last != nil else {
if resultBlock != nil {
resultBlock!(nil, "没有获取到用户位置信息")
}
return
}
resultBlock!(locations.last,nil)
if isOnce {
manager.stopUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .denied:
resultBlock!(nil,"当前被拒绝")
case .restricted:
resultBlock!(nil,"当前受限制")
case .notDetermined:
resultBlock!(nil,"用户没决定")
default:
print("nono")
}
}
}