前言
在移动开发中,定位是非常重要的功能。移动端能够定位是有别于PC的最大原因。
实践
CLLocationManager
iOS为我们提供了位置服务类CLLocationManager。
LocationManager.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
@interface LocationManager : NSObject<CLLocationManagerDelegate>
@property (strong,strong ) CLLocationManager *locationManager;//定位服务
@property (nonatomic,copy) NSString *currentCity;//城市
@property (nonatomic,copy) NSString *strLatitude;//经度
@property (nonatomic,copy) NSString *strLongitude;//维度
- (void)getLocation;
@end
LocationManager.m
#import "LocationManager.h"
@implementation LocationManager
CLLocationManager *_locationManager;//定位服务
NSString *_currentCity;//城市
NSString *_strLatitude;//经度
NSString *_strLongitude;//维度
同时,CLLocationManager给我们提供了一些关于LBS的配置:
// LBS的精度选择,如设置10就只保证10米的精度。谨慎地选择精度,可以省电。
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// LBS的更新距离,如设置10表示,当位置改变超过10米时,会调用位置更新的回调。
_locationManager.distanceFilter = kCLDistanceFilterNone;
// LBS的回调代理,回调定位的更新or失败。
_locationManager.delegate = self;
#pragma mark - 定位失败
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
printf("定位失败\n");
}
#pragma mark - 定位成功
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
printf("定位成功");
}
权限
定位功能在iOS系统中是一个需要权限的功能。我们在Info.plist
文件中,添加定位权限和相关的权限描述。这样当我们需要使用时,系统就会弹窗,用我们的权限描述来问用户,是否需要打开定位权限。
在Info.plist中完成描述后,我们在调用获取位置的方法时,也要先申请权限。
requestWhenInUseAuthorization vs requestAlwaysAuthorization
这两个权限简单来说,一个是需要App在前台才能够使用定位的功能,另一个是在后台也可以使用定位的功能。
具体的情况和trick点,苹果官方都有比较详细的说明,不再赘述。
最终,我们在LocationManager.m中的代码是:
#import "LocationManager.h"
@implementation LocationManager
CLLocationManager *_locationManager;//定位服务
NSString *_currentCity;//城市
NSString *_strLatitude;//经度
NSString *_strLongitude;//维度
- (void)getLocation{
printf("OC get location\n");
if ([CLLocationManager locationServicesEnabled]) {
_currentCity = [[NSString alloc]init];
if (_locationManager == NULL) {
_locationManager = [[CLLocationManager alloc]init];
_locationManager.delegate = self;
[_locationManager requestWhenInUseAuthorization];
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.distanceFilter = kCLDistanceFilterNone;
[_locationManager startMonitoringSignificantLocationChanges];
}
printf("start update location\n");
[_locationManager startUpdatingLocation];
}
}
#pragma mark - 定位失败
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
printf("定位失败\n");
printf("%s", error.code);
}
#pragma mark - 定位成功
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
printf("定位成功");
[_locationManager stopUpdatingLocation];
CLLocation *currentLocation = [locations lastObject];
CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
//当前的经纬度
NSLog(@"当前的经纬度 %f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude);
//这里的代码是为了判断didUpdateLocations调用了几次 有可能会出现多次调用 为了避免不必要的麻烦 在这里加个if判断 如果大于1.0就return
NSTimeInterval locationAge = -[currentLocation.timestamp timeIntervalSinceNow];
if (locationAge > 1.0){//如果调用已经一次,不再执行
return;
}
//地理反编码 可以根据坐标(经纬度)确定位置信息(街道 门牌等)
[geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (placemarks.count >0) {
CLPlacemark *placeMark = placemarks[0];
_currentCity = placeMark.locality;
if (!_currentCity) {
_currentCity = @"无法定位当前城市";
}
//看需求定义一个全局变量来接收赋值
NSLog(@"当前国家 - %@",placeMark.country);//当前国家
NSLog(@"当前城市 - %@",_currentCity);//当前城市
NSLog(@"当前位置 - %@",placeMark.subLocality);//当前位置
NSLog(@"当前街道 - %@",placeMark.thoroughfare);//当前街道
NSLog(@"具体地址 - %@",placeMark.name);//具体地址
NSString *message = [NSString stringWithFormat:@"%@,%@,%@,%@,%@",placeMark.country,_currentCity,placeMark.subLocality,placeMark.thoroughfare,placeMark.name];
}else if (error == nil && placemarks.count){
NSLog(@"NO location and error return");
}else if (error){
NSLog(@"loction error:%@",error);
}
}];
}
@end
补充学习点
由于我外部的代码,使用了Swift,在写完LocationManager后,就涉及到Swift调用OC类的问题。
苹果给出的方法是:会新建一个文件叫<ProjectName>-Bridging-Header.h
我们在其中添加,OC类:
#import "LocationManager.h"
然后就可以直接在Swift中调用了
var locationManager : LocationManager = LocationManager()
...
locationManager.getLocation()
以上,初学iOS。如有问题,欢迎指正。
网友评论