CoreLocation框架可用于定位设备当前经纬度,通过该框架,应用程序可通过附近的蜂窝基站,WIFI信号或者GPS等信息计算用户位置。
iOS定位支持的3种模式。
(1)GPS卫星定位
(2)基站定位
(3)WiFi
iOS开发者使用CoreLocation.framework框架进行定位非常简单,CoreLocation框架的常用API主要有如下几个。
(1)CLLocationManger:定位管理器类。
(2)CLLocationManagerDelegate:该协议代表定位管理器的delegate协议。实现该协议的对象可负责处理CLLocationManager的定位事件。
(3)CLLocation:该对象代表位置。该对象包含了当前设备的经度、纬度、高度、速度、路线等信息,还包含了该定位信息的水平精确度,垂直精确度以及时间戳信息。
(4)CLHeading:该对象代表设备的移动方向。
(5)CLRegion:该对象代表一个区域。一般程序不会直接使用该类,而是使用它的两个子类,即CLCircularRegion(圆形区域)和CLBeaconRegion(蓝牙信号区)。
1.获取位置信息
(1)创建CLLocationManager对象,该对象负责获取定位相关信息。并为该对象设置一些必要的属性。
(2)为CLLocationManager指定delegate属性,该属性值必须是一个实现CLLocationManagerDelegate协议的对象。实现CLLocationManagerDelegate协议时可根据需要实现协议中特定的方法。
(3)调用CLLocationManager的startUpdatingLocation方法获取定位信息。定位结束时,可调用stopUpdatingLocation方法结束获取定位信息。
案例:
第一步:在CoreLocation.framework添加到项目中去
第二步:在iOS8中需要在info.plist中添加两个字段。
代码如下:
#import "ViewController.h" #import <CoreLocation/CoreLocation.h> @interface ViewController ()<CLLocationManagerDelegate> @property (weak, nonatomic) IBOutlet UITextField *longitude; @property (weak, nonatomic) IBOutlet UITextField *latitude; @property (weak, nonatomic) IBOutlet UITextField *height; @property (weak, nonatomic) IBOutlet UITextField *speed; @property (weak, nonatomic) IBOutlet UITextField *direction; @property(strong,nonatomic)CLLocationManager *locationManager; @end @implementation ViewController - (IBAction)beginLocation:(UIButton *)sender { if ([CLLocationManager locationServicesEnabled]) { NSLog(@"开始执行定位服务"); //设定定位精度:最佳精度 self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; //设置距离过滤器为50米,表示每移动50米更新一次位置 self.locationManager.distanceFilter = 50; //将视图控制器自身设置为CLLocationManager的delegate //因此该视图控制器需要实现CLLocationManagerDelegate协议 self.locationManager.delegate = self; } else { NSLog(@"无法使用定位服务"); } } -(void) viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; //开启定位 [_locationManager startUpdatingLocation]; } -(void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; //结束定位 [_locationManager stopUpdatingLocation]; } #pragma mark - CLLocationDelegate代理协议 //成功获取定位数据后将会激发该方法 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { //获取最后一个定位数据 CLLocation *location = [locations lastObject]; //依次获取CLLocation中封装的经度、纬度、高度、速度、方向等信息 self.longitude.text = [NSString stringWithFormat:@"%g",location.coordinate.longitude];//纬度 NSLog(@"%f",location.coordinate.longitude); self.latitude.text = [NSString stringWithFormat:@"%g",location.coordinate.latitude];//经度 self.height.text = [NSString stringWithFormat:@"%g",location.altitude]; self.speed.text = [NSString stringWithFormat:@"%g",location.speed]; self.direction.text = [NSString stringWithFormat:@"%g",location.course]; } //定位失败执行的操作 -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"定位失败:%@",error); } - (void)viewDidLoad { [super viewDidLoad]; //创建CLLocationManager对象 self.locationManager = [[CLLocationManager alloc]init]; } @end
运行效果图,如下:
方向监测
拥有GPS硬件的设备可以生成设备的当前方向(course属性)和速度信息。iPhone设备携带的定位管理器可以返回一个已经计算好的course值,通过这个值我们可以获得当前前进的方向,course值是0~360之间的浮点数,0°值表示正北方向,90°表示正东方向,180°值表示正南方向,270°值表示正西方向,程序可以通过course值来检测用户位置的移动方向。除此之外,还可以通过磁力计来获取设备的真实方向。
使用CLLocationManager获取设备方向的步骤如下。
1.创建CLLocationManager对象,该对象负责获取定位相关信息,并为该对象设置一些必要的属性。
2.为CLLocationManager指定delegate属性,该属性值必须是一个实现CLLocationManagerDelegate协议的对象。实现CLLocationManagerDelegate协议时可根据需要实现协议中特定的方法。
3.调用CLLocationManager的startUpdatingHeading方法获取方向信息。获取方向结束时,可调用stopUpdatingHeading方法结束时获取方向信息。
当设备的方向改变时,iOS系统就会自动激发CLLocationManager的delegate对象的locationManager:didUpdateHeading:方法,而程序可通过重写该方法来获取设备方向。
iOS允许为检测方向改变设置如下属性。
1)CLLocationDegress headingFilter:设置只有当设备方向的改变值超过该属性值时才激发delegate的方法。
2)CLDeviceOrientation headingOrientation:设置设备当前方向。
监听方向时返回的是一个CLHeading对象,该对象包含以下属性。
1)magnticHeading:该属性返回设备与磁北的相对方向。
2)trueHeading:该属性返回设备与真北的相对方向。
3)headingAccuracy:该属性返回方向值的误差范围。
4)timestamp:该属性返回方向值的生成时间。
#import "ViewController.h" #import <CoreLocation/CoreLocation.h> @interface ViewController ()<CLLocationManagerDelegate> { CALayer *znzLayer; } @property(strong,nonatomic)CLLocationManager *locationManager; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //如果磁力计可用,则开始监听方向改变 if ([CLLocationManager headingAvailable]) { //创建显示方向的指南针图片Layer; znzLayer = [[CALayer alloc]init]; NSInteger screenHeight = [UIScreen mainScreen].bounds.size.height; NSInteger y = (screenHeight - 320)/2; znzLayer.frame = CGRectMake(0, y, 320, 320); //设置znzLayer显示的图片 znzLayer.contents = (id)[[UIImage imageNamed:@"1.png"]CGImage]; //将znzLayer添加到系统的UIView中 [self.view.layer addSublayer:znzLayer]; //创建CLLocationManager对象 self.locationManager = [[CLLocationManager alloc]init]; self.locationManager.delegate = self; [self.locationManager startUpdatingHeading]; } else { [[[UIAlertView alloc]initWithTitle:@"提醒" message:@"您的设备不支持磁力计" delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil]show]; } } #pragma mark - CLLocationManagerDelegate代理方法 -(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { //将设备的方向换算成弧度 CGFloat headings = -1.0f *M_PI * newHeading.magneticHeading / 180.0f; //创建不断改变CALayer的transform属性的属性动画 CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"]; CATransform3D fromValue = znzLayer.transform; //设置动画开始的属性值 anim.fromValue = [NSValue valueWithCATransform3D:fromValue]; //绕Z轴旋转heading弧度的变换矩阵 CATransform3D toValue = CATransform3DMakeRotation(headings, 0, 0, 1); //设置动画结束时的属性 anim.toValue = [NSValue valueWithCATransform3D:toValue]; anim.duration = 0.5; anim.removedOnCompletion = YES; //设置动画结束后znzLayer的变换矩阵 znzLayer.transform = toValue; //为znzLayer添加动画 [znzLayer addAnimation:anim forKey:nil]; } -(BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager { return YES; } @end
区域监测
如果希望iOS设备进入某个区域发出通知,那么这种区域监测的功能也被称为临近警告。所谓临近警告的示意图如下:
用户设备不断地临近指定固定点,当与该固定点的距离小于指定范围时,系统可以触发相应的处理。用户设备离开指定固定点,当与该固定点的距离大于指定范围时,系统也可以触发相应的处理。
iOS的区域监测同样可以使用CLLocationManager来实现,监听设备是否进入/离开某个区域的步骤如下:
1)创建CLLocationManager对象,该对象负责获取定位相关信息,并未该对象设置一些必要的属性。对于区域监测而言,CLLocationManager对象需要设置monitoredRegions属性,该属性值用于设置该设备监听的多个区域。
2)为CLLocationManager指定delegate属性,该属性值必须是一个实现CLLocationManagerDelegate协议的对象。实现CLLocationManagerDelegate协议时可根据需要实现协议中特定的方法。
3)调用CLLocationManager的startMonitoringForRegion:方法进行区域监测。区域监测结束时,可调用stopMonitoringForRegion:方法结束区域监测。
#import "ViewController.h" #import <CoreLocation/CoreLocation.h> @interface ViewController ()<CLLocationManagerDelegate> @property(strong,nonatomic)CLLocationManager *locationManager; @end @implementation ViewController -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.locationManager startUpdatingLocation]; } - (void)viewDidLoad { [super viewDidLoad]; //判断是否开启定位服务 if ([CLLocationManager locationServicesEnabled]) { self.locationManager = [[CLLocationManager alloc]init]; //定义一个CLLocationCoordinate2D作为区域的圆心 CLLocationCoordinate2D companyCenter; companyCenter.latitude = 23.126272; companyCenter.longitude = 113.395568; //使用CLCircularRegion创建一个圆形区域,半径为500米 CLRegion *fkit = [[CLCircularRegion alloc]initWithCenter:companyCenter radius:500 identifier:@"fkit"]; //开始监听fkit区域 [self.locationManager startMonitoringForRegion:fkit]; self.locationManager.delegate = self; [self.locationManager requestAlwaysAuthorization]; } else { [[[UIAlertView alloc]initWithTitle:@"提醒" message:@"您的设备不支持定位" delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil]show]; } [self.locationManager startUpdatingLocation]; } #pragma mark - CLLocationManagerDelegate代理方法 //进入指定区域以后弹出提示框提示用户 -(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { [[[UIAlertView alloc]initWithTitle:@"区域检测提示" message:@"您已经【进入】中关园区域" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]show]; } //离开指定区域以后将弹出提示框提示用户 -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { [[[UIAlertView alloc]initWithTitle:@"区域检测提示" message:@"您已经【离开】中关园区域" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]show]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. }