LBS(定位服务)pLocation Based Service  ———— 地图

来源:互联网 发布:淘宝出售假冒商品投诉 编辑:程序博客网 时间:2024/05/23 11:32
知识点:

1.CoreLocation框架—负责定位的(手机的)位置。用于地理定位
2.MapKit.framework—系统自带的框架,地图展示,
3.ios7 中:系统会自动申请用户位置权限。
CoreLocation中使用CLLocationManager对象来做用户定位,
CoreLocation框架中所有数据类型的前缀都是CL
定位的类(位置管理器最好懒加载创建,强引用):CLLocationManager ,用alloc init,创建 ,监听用代理,实现代理方法, 开始更新用户的位置【位置管理器的对象 startUpdatingLocation】,
用来表示经纬度的结构体——CLLocationCoordinate2D 
latitude —纬度  longitude — 经度 course —朝向  timeStamp —更新的点的时间, 测试楼层--floor

4.ios8之后,要做一个判断,如果是,要申请用户权限。代理方法---判断授权状态,status  在Info。plist文件中配置Key值,(当用户在前台还是后台的时候。 请求数据   request。。。。)---代理方法---判断授权状态,

5.调整位置的经纬度—deBug 中的location;

6.位置管理器的常见属性
当用户移动了多长的距离之后,才更新用户的位置(米),对象.distanceFilter =10;
定位精度(精度越高越费电):对象.desiredAccuracy  =kCLLocationAccuracyBestForNavigation;   
extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation;导航使用最好进度
//    extern const CLLocationAccuracy kCLLocationAccuracyBest; 最高精度
//    extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;  10M
//    extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters; 100M
//    extern const CLLocationAccuracy kCLLocationAccuracyKilometer; 1000M
//    extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers; 3000M
导航的使用场景要用activityType =定位数据的用途 self.locationManager.activityType =CLActivityTypeFitness;
//    CLActivityTypeOther = 1,
//    CLActivityTypeAutomotiveNavigation, //汽车导航
//    CLActivityTypeFitness, // 步行导航
//    CLActivityTypeOtherNavigation // 其他导航,比如轮船,火车,飞机
//   
CLLocation用来表示某个位置的地理信息,比如经纬度、海拔等等。常见属性
CLLocationCoordinate2D coordinate;表示经纬度
CLLocationDistance altitude;表示海拔
CLLocationDirection course;表示路线,航向(取值范围是0.0° ~ 359.9°,0.0°代表真北方向)
CLLocationSpeed speed;表示行走速度(单位是m/s)

  • 用- (CLLocationDistance)distanceFromLocation:(constCLLocation *)location方法可以计算2个位置之间的距离
  • 计算两个时间点之间的时间差的方法: self.sumTime += [currentLocation.timestamptimeIntervalSinceDate:self.preLocation.timestamp];
计算平均速度案例:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
 CLLocation *currentLocation = locations.lastObject;

    if (self.preLocation ==nil) {
        self.preLocation = currentLocation;
        return;
    }
//  计算地图上两点之间的距离,以米为单位的
    self.sumDistance += [currentLocationdistanceFromLocation:self.preLocation];
    self.sumTime += [currentLocation.timestamp timeIntervalSinceDate:self.preLocation.timestamp];
   
//  计算平均速度
    CGFloat avgSpeed = self.sumDistance / self.sumTime;
   
    NSLog(@"总距离:%lf,总时间:%lf,平均速度:%lf",self.sumDistance,self.sumTime,avgSpeed);

}
CLHeading:用来表示方向相关的数据
//更新用户的方向
    [self.locationManager startUpdatingHeading];
  • @property(readonly,nonatomic) CLLocationDirection magneticHeading
  • 磁北偏移量, 0度表示磁北, 0 – 359.9
  • 磁北: 磁场北极,是指南针所指的北
  • @property(readonly,nonatomic) CLLocationDirection trueHeading
  • 真北偏移量, 0度表示真北
  • 真北:地理北极, 是地图或者地球仪上所有经线的起始点
设置指南针案例:

#import "ViewController.h"
#import
<CoreLocation/CoreLocation.h>
@interface ViewController ()<CLLocationManagerDelegate>
@property (weak,nonatomic) IBOutlet UIImageView *compass;指南针
@property(nonatomic,strong)CLLocationManager * locationManager ;
@end

@implementation ViewController
#pragma mark -懒加载要在真机上试
-(CLLocationManager *)locationManager{
   
    if (!_locationManager) {
       
        _locationManager = [[ CLLocationManager alloc]init];
       
        _locationManager.delegate =self;
       
    }
    return _locationManager;
}
- (void)viewDidLoad {
    [super viewDidLoad];
//   获取用户朝向,没有涉及用户的隐私,不需要请求用户的授权
    //更新用户的方向
    [self.locationManager startUpdatingHeading];
}
#pragma mark -代理方法
//当手机的朝向发生改变的时候执行该代理方法  newHeading:用于描述方位的类
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
   
    //    相对于磁北极偏移量:(0.0 - 359.9 degrees)
    //    newHeading.magneticHeading
    //    相对于真北极的偏移量
    //    newHeading.trueHeading;(0.0 - 359.9 degrees)
   
    double degrees = newHeading.magneticHeading;
   
    //角度值转换弧度值
    CGFloat angle = degrees / (180 /M_PI);
   
    //由于偏移方向与transform的方向是相反的
    self.compass.transform =CGAffineTransformMakeRotation(-angle);
   
}

CLRegion:区域
子类:CLCircularRegion   表示圆形范围:属性:radius 和center

CLLocationCoordinate2D:表示是一个用来表示经纬度的结构体,

typedef struct {

        CLLocationDegrees latitude; // 纬度

        CLLocationDegrees longitude;// 经度


} CLLocationCoordinate2D;
一般用CLLocationCoordinate2DMake函数来创建CLLocationCoordinate2D


7.计算地图上两点之间的距离(CLLocation
对象) = locations.lastObject; distanceFromLocation:方法计算两点间的距离


8.监听用户区域( 请求总是授权):【对象  requestAlwaysAuthorization】表示应用不管在前台还是后台,都可以监听用户的地理位置,开发者在Info.plist中设置NSLocationUsageDescription说明定位的目的 
当要监听用户区域改变,那么必须请求总是授权


requestWhenInUseAuthorization 只有当前应用在前台的时候,才需要使用用户的位置 需要在info.plist文件中配置NSLocationWhenInUseUsageDescription key来说明使用用户位置的原因

开始监听用户的区域:【  startMonitorngForRegion:】用代理方法(当用户进入监听区域的时候,执行代理方法  didEnterRegion:   离开的时候执行:didExitRegion:)
ClRegion:描述地图上的一块区域的,通常用他的子类 CLCircularRegion  initWithCenter:创建

9.指南针:要生成证书  fix Issue 
获取用户的朝向,没有涉及到用户的隐私。不需要请求用户授权,【对象  startUpdatingHeadIng】——更新用户方向。遵守代理方法 didUpdateHeading:  
newsHeading.magneticHeading ——相对于磁北极:(取值范围:0.0——359.9 degrees角度值—要转为弧度制    degrees / (180/M_PI))在设置指南针的偏移量:transfuse ----用make,弧度值为负的,因为是方向是相反的
相对于真北极的偏移量--------newsHeading.trueHeading


10.CLGeocoder: 可以完成“地理编码”和“反地理编码”  (创建)地理编码器
地理编码:把地名转换成经纬度
反地理编码:把经纬度信息转换成地名
地理编码方法:
- (void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;
这个方法会访问苹果位置的服务器来返回数据。
CLPlaceMark  :地标—— 描述了地理发经纬度,地名,省,市,区,街道。
  • CLPlacemark的字面意思是地标,封装详细的地址位置信息
  • @property (nonatomic,readonly) CLLocation *location;
  • 地理位置
  • @property (nonatomic,readonly) CLRegion *region;
  • 区域
  • @property (nonatomic,readonly) NSDictionary *addressDictionary;
  • 详细的地址信息
  • @property (nonatomic,readonly) NSString *name;
  • 地址名称
  • @property (nonatomic,readonly) NSString *locality;
  • 城市
例子:
#import "ViewController.h"
#import
<CoreLocation/CoreLocation.h>
@interface ViewController ()
@property (weak,nonatomic) IBOutlet UITextField *address;

@property (weak,nonatomic) IBOutlet UITextField *latitude;
@property (weak,nonatomic) IBOutlet UITextField *longitude;
@property (weak,nonatomic) IBOutlet UILabel *latitudeLable;
@property (weak,nonatomic) IBOutlet UILabel *longitudeLable;
@property (weak,nonatomic) IBOutlet UILabel *addressLable;
@end

@implementation ViewController
#pragma mark -地理编码
- (IBAction)Geogidute:(id)sender {
   
    NSString * adress = self.address.text;
   
    if (adress.length ==0) {
       
        NSLog(@"请输入地名");
       
        return;
    }
   
//    地理编码器 创建
    CLGeocoder * geocoder = [[ CLGeocoder alloc]init];
   
    //地理编码:把地名转换成经纬度 有个方法 这个方法会访问苹果位置的服务器,来返回数据
    [geocoder geocodeAddressString:adresscompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
       
//       CLPlacemark 地标:描述了地理的经纬度,地名:省市区
      //要遍历这个地标,因为地球上相同名字的地方会有很多个
        [placemarks enumerateObjectsUsingBlock:^(CLPlacemark *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
           
//            经纬度
            CLPlacemark * placemark = obj;
           
            CLLocationCoordinate2D coordinate = placemark.location.coordinate;
//            名称
            NSLog(@"%lf,%lf",coordinate.latitude,coordinate.longitude);
            NSLog(@"%@",placemark.name);
           
            NSLog(@"%@(直辖市) %@ %@",placemark.administrativeArea,placemark.locality,placemark.subLocality);
           
            self.latitudeLable.text = [NSString stringWithFormat:@"%lf",coordinate.latitude];
           
            self.longitudeLable.text = [NSString stringWithFormat:@"%lf",coordinate.longitude];
           
            self.addressLable.text = placemark.name;
        }];
       
   
    }];
   
}
反地理编码方法
- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;
例子:
#import "ViewController.h"
#import
<CoreLocation/CoreLocation.h>
@interface ViewController ()
@property (weak,nonatomic) IBOutlet UITextField *address;

@property (weak,nonatomic) IBOutlet UITextField *latitude;
@property (weak,nonatomic) IBOutlet UITextField *longitude;
@property (weak,nonatomic) IBOutlet UILabel *latitudeLable;
@property (weak,nonatomic) IBOutlet UILabel *longitudeLable;
@property (weak,nonatomic) IBOutlet UILabel *addressLable;
@end

@implementation ViewController
#pragma mark -反地理编码
- (IBAction)reverseGeogidute:(id)sender {
   
    NSString *latitudeStr = self.latitude.text;
   
    NSString *longitudeStr = self.longitude.text;
   
    if (latitudeStr.length ==0) {
       
        NSLog(@"请输入纬度信息");
        return;
    }
    if (longitudeStr.length ==0) {
       
        NSLog(@"请输入经度信息");
        return;
    }
   
   
    //创建地理编码器
   
    CLGeocoder * geocoder = [[ CLGeocoder alloc]init];
   
    //创建位置对象
    CLLocation * location = [[ CLLocation alloc]initWithLatitude:latitudeStr.doubleValuelongitude:longitudeStr.doubleValue];
    //反地理编码
    [ geocoder reverseGeocodeLocation:locationcompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
      
        [placemarks enumerateObjectsUsingBlock:^(CLPlacemark *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//            地标
            CLPlacemark * placemark = obj;
           
//            经纬度
            CLLocationCoordinate2D coordinate = placemark.location.coordinate;
           
            NSLog(@"%lf,%lf",coordinate.latitude,coordinate.longitude);
            NSLog(@"%@",placemark.name);
           
            NSLog(@"%@(直辖市) %@ %@",placemark.administrativeArea,placemark.locality,placemark.subLocality);
           
            self.latitudeLable.text = [NSString stringWithFormat:@"%lf",coordinate.latitude];
           
            self.longitudeLable.text = [NSString stringWithFormat:@"%lf",coordinate.longitude];
           
            self.addressLable.text = placemark.name;
           
        }];
    }];
}

系统地图。
1.地图的基本使用
控件栏里的Map View 需要导入对应框架  mapKit.framework 动态库里设置
导入头文件<mapKit>
  • MapKit框架中所有数据类型的前缀都是MK
  • MapKit有一个比较重要的UI控件 :MKMapView,专门用于地图显示
  • 可以通过设置MKMapView的mapViewType设置地图类型
  • MKMapTypeStandard :普通地图
  • MKMapTypeSatellite :卫星云图 
  • MKMapTypeHybrid :混合地国

跟踪显示用户的位置 userTrackingMode 首先要用户授权,
  • 设置MKMapView的userTrackingMode属性可以跟踪显示用户的当前位置
  • MKUserTrackingModeNone :不跟踪用户的位置
  • MKUserTrackingModeFollow :跟踪并在地图上显示用户的当前位置
  • MKUserTrackingModeFollowWithHeading :跟踪并在地图上显示用户的当前位置,地图会跟随用户的前进方向进行旋转
  • MKMapView可以设置一个代理对象,用来监听地图的相关行为
  • 常见的代理方法有
  • - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation;
  • 一个位置更改默认只会调用一次,不断监测用户的当前位置
  • 每次调用,都会把用户的最新位置(userLocation参数)传进来
  • - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
  • 地图的显示区域即将发生改变的时候调用
  • - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
  • 地图的显示区域已经发生改变的时候调用
  • #pragma mark -用户更新位置时执行
    /// iOS7 中用于显示用户所在地图区域,iOS8以后,可以修改默认的跨度.
    -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
       
        //   MKCoordinateRegion  用于描述地图一块区域
    //    跨度
        MKCoordinateSpan span = MKCoordinateSpanMake(0.01,0.01);
    //    区域
        MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.location.coordinate, span);
        //  设置地图的显示区域
        [ self.mapViewsetRegion:region];
       
    }

添加大头针:系统自带的 MKpointAnnotation大头针模型(标注)——需要经纬度(大头针的点位置)。设置标题title,subTitle子标题在添加到地图上去大头针

自定义大头针:(可以设置样式,大头针颜色(pinColor只有三种颜色 ---canShowCallout这个属性可以出现前面默认设置好的泡泡视图,因为这边涉及到重用。设置泡泡视图的辅助视图用到的属性:left/rightCalloutAccessoryView:button或自定义控件。 ios9新增属性:pinTintColor(各种颜色)),ios8增加的属性:坠落动画:animatesDrop为YES。在代理方法中,mapView:viewForAnnotation:定义 ,返回大头针视图;如果返回nil 就是默认大头针,

if( 模型对象 iskindofclass :模型 class)

自定义大头针设置样式:定义大头针模型:新建一个类继承自NSObject。在类中,遵从大头针模型协议只会生成get方法。:导入mapkit框架,删除foundation框架。设置属性,枚举类型,

点转换成经纬度的方法:
 
    UITouch *touch = [touches anyObject];

    CGPoint point = [touch locationInView:self.view];
   
    CLLocationCoordinate2D coodinate = [self.mapViewconvertPoint:point toCoordinateFromView:self.view];

经纬度转换成点的方法: - (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(nullableUIView *)view;



MKMapItem也是地标(创建地图的地标对象)。只有两种使用场景:1.跳转原生地图,2. 计算线路    
1.跳转原生地图:案例
#import "ViewController.h"
#import
<MapKit/MapKit.h>
@interface ViewController ()

@property (weak,nonatomic) IBOutlet UITextField *startAddress;
@property (weak,nonatomic) IBOutlet UITextField *endAddress;
@end

@implementation ViewController

- (IBAction)lookHeading:(id)sender {
   
    NSString * startStr  = self.startAddress.text;
    NSString * endStr  = self.endAddress.text;
    //判断用户是否输入
    if (startStr.length ==0) {
       
        NSLog(@"请输入始发地");
        return;
    }
    if (endStr.length ==0) {
       
        NSLog(@"请输入目的地");
        return;
    }
   
    //地理编码
    CLGeocoder * geocoder = [[ CLGeocoder alloc]init];
    [ geocoder geocodeAddressString:startStrcompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
       
        //      多个对象应该如何过滤呢?
        //      1. 一般我们遍历,然后所在位置是否在用户所在区域
        //      2. 有时候我们也会选用距离用户最近的点
       
        CLPlacemark * placemark = placemarks.lastObject;
        //      MKMapItem 使用场景: 1. 跳转原生地图 2.计算线路
        //        [MKMapItem mapItemForCurrentLocation]当前用户的位置.注意如果使用它就必须先请求用户位置权限
        //创建一个地图的地标对象
        MKPlacemark * startPlacemark = [[MKPlacemark alloc]initWithPlacemark:placemark];
        MKMapItem * startMapItem = [[ MKMapItem alloc]initWithPlacemark:startPlacemark];
       
        [ geocoder geocodeAddressString:endStrcompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
           
            CLPlacemark * placemark = placemarks.lastObject;
           
            MKPlacemark * endPlacemark = [[MKPlacemark alloc]initWithPlacemark:placemark];
            MKMapItem * endMapItem = [[MKMapItem alloc]initWithPlacemark:endPlacemark];
            //           这个方法只能在地图标注一个点
            //            [startMapItem openInMapsWithLaunchOptions:<#(nullable NSDictionary<NSString *,id> *)#>]
           
            //          MKLaunchOptionsDirectionsModeKey指定导航模式
            //            NSString * const MKLaunchOptionsDirectionsModeDriving;驾车
            //            NSString * const MKLaunchOptionsDirectionsModeWalking;步行
            //            NSString * const MKLaunchOptionsDirectionsModeTransit;动车或者高铁
           
            NSDictionary * lauchOptions =@{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeWalking};//步行
           
            //打开原生地图进行导航
            [ MKMapItem openMapsWithItems:@[startMapItem,endMapItem]launchOptions:lauchOptions];
        }];
       
    }];
}
0 0
原创粉丝点击