地图的显示
MapKit框架的使用:
导入框架(iOS5之后不在需要程序员自己导入)
导入主头文件 #import<MapKit/MapKit.h>
MapKit框架使用须知:
MapKit框架中所有数据类型的前缀都是MK
MapKit有一个比较重要的UI控件:
MKMapView
,专门用于地图显示.
跟踪显示用户的位置: 设置MKMapView
的userTrackingMode
属性可以跟踪显示用户的当前位置.
MKUserTrackingModelNone:
不跟踪用户的位置
MKUserTrackingModelFollow:
跟踪并在地图上显示用户的当前位置
MKUserTrackingModelFollowWithHeading:
跟踪并在地图上显示用户的当前位置,地图会跟随用户的前进方向进行旋转
先创建两个类,一个Annotation,CustomAnnotation声明一样的属性,用于自定义大头针用
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface Annotation : NSObject<MKAnnotation>//遵循协议
@property (nonatomic)CLLocationCoordinate2D coordinate;
//标题
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy)NSString *subtitle;
//大头针的详情描述
@property (nonatomic, copy)NSString *detail;
//星际评价
@property (nonatomic, strong) UIImage *star;
@end
再创建一个CustomAnnotationView,用于取出自定义的大头针视图
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "CustomAnnotation.h"
@interface CustomAnnotationView : MKAnnotationView
@property (nonatomic, strong)CustomAnnotation *customAnnotation;
#pragma mark----从缓存中取出大头针-----------
+(instancetype)calloutViewWithMapView:(MKMapView *)mapView;
@end
#import "CustomAnnotationView.h"
@interface CustomAnnotationView ()
//展示详情
@property (nonatomic, strong) UILabel *detaillabel;
//展示星级评价
@property (nonatomic, strong) UIImageView *startView;
@end
@implementation CustomAnnotationView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
_detaillabel = [[UILabel alloc]init];
_detaillabel.backgroundColor = [UIColor whiteColor];
_startView = [[UIImageView alloc]init];
_startView.backgroundColor = [UIColor whiteColor];
[self addSubview:_detaillabel];
[self addSubview:_startView];
}
return self;
}
#pragma mark-----当给大头针视图设置大头针模型时,可在此根据模型设置视图内容------
- (void)setAnnotation:(CustomAnnotation *)annotation{
[super setAnnotation:annotation];
//根据模型调整布局
//详情
self.detaillabel.text = annotation.detail;
self.detaillabel.frame = CGRectMake(0, 0, 100, 15);
self.detaillabel.font = [UIFont systemFontOfSize:12];
//星级
_startView.image = annotation.star;
_startView.frame = CGRectMake(0, 14, 100, 15);
}
+(instancetype)calloutViewWithMapView:(MKMapView *)mapView{
static NSString *callout = @"callkey";
CustomAnnotationView *calloutview = (CustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:callout];
if (!calloutview) {
calloutview = [[CustomAnnotationView alloc]init];
}
return calloutview;
}
@end
地图,系统大头针,自定义大头针
#import "FirstViewController.h"
#import <MapKit/MapKit.h>//引入头文件
#import "Annotation.h"
#import "CustomAnnotation.h"
#import "CustomAnnotationView.h"
@interface FirstViewController ()<MKMapViewDelegate>
@property (nonatomic, strong) MKMapView *mapview;
@property (nonatomic) CLLocationCoordinate2D center;
@property (nonatomic, strong)MKPointAnnotation *pointAnnotation;
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
#pragma mark------自带地图-------
_mapview = [[MKMapView alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
//触摸缩放
_mapview.zoomEnabled = YES;
//可移动的
self.mapview.scrollEnabled = YES;
//设置地图形式
self.mapview.mapType = MKMapTypeHybrid;
//设置代理
self.mapview.delegate = self;
//显示用户位置
self.mapview.showsUserLocation = YES;
[self.view addSubview:_mapview];
[self addAnnotation];
//添加一个长按手势
UILongPressGestureRecognizer *longshow = [[UILongPressGestureRecognizer alloc ]initWithTarget:self action:@selector(longclick:)];
[self.mapview addGestureRecognizer:longshow];
}
- (void)longclick:(UILongPressGestureRecognizer *)sender{
//判断在长按的起始点落下大头针
if (sender.state == UIGestureRecognizerStateBegan) {
//首先获取这个点
CGPoint point = [sender locationInView:self.mapview];
//将这个点转换为经纬度坐标
self.center = [self.mapview convertPoint:point toCoordinateFromView:self.mapview];
//初始化大头针坐标点对象
self.pointAnnotation = [[MKPointAnnotation alloc]init];
//将转换后的经纬度赋值给此对象
self.pointAnnotation.coordinate = self.center;
self.pointAnnotation.title = @"长按";
[self.mapview addAnnotation:self.pointAnnotation];
}
}
#pragma mark------------------添加大头针----------------
- (void)addAnnotation{
CLLocationCoordinate2D location2 = CLLocationCoordinate2DMake(39.9200225351, 116.3968733177);
Annotation *annotationGG = [[Annotation alloc]init];
annotationGG.title = @"Start";
annotationGG.subtitle = @"故宫";
//设置坐标
annotationGG.coordinate = location2;
annotationGG.detail = @"前门";
annotationGG.star = [UIImage imageNamed:@"star"];
//添加大头针
[self.mapview addAnnotation:annotationGG];
}
#pragma mark--- 显示大头针调用此方法---------
//表示即将要显示的大头针
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[CustomAnnotation class]]) {
//自定义大头针弹出视图详情本身没有弹出交互功能,(canShowCallout = false,默认值)可在有弹出交互的大头针里添加其他视图
CustomAnnotationView *custom = [CustomAnnotationView calloutViewWithMapView:mapView];
custom.annotation = annotation;
return custom;
}
return nil;//返回值为nil,显示是默认的大头针
}
#pragma mark-----选中大头针时触发-----
//点击一般大头针Annotation,添加一个自定义大头针视图作为所点大头针弹出的视图详情
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
Annotation *annotation = view.annotation;
if ([view.annotation isKindOfClass:[Annotation class]]) {
[self removeCustomAnnotation];
CustomAnnotation *annotation1 = [[CustomAnnotation alloc]init];
annotation1.detail = annotation.detail;
annotation1.star = annotation.star;
annotation1.coordinate = view.annotation.coordinate;
[mapView addAnnotation:annotation1];
}
}
#pragma mark----移除大头针的自定义视图------------
- (void)removeCustomAnnotation{
[self.mapview.annotations enumerateObjectsUsingBlock:^(id<MKAnnotation> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[CustomAnnotation class]]) {
[self.mapview removeAnnotation:obj];
}
}];
}
#pragma mark----点击空白区域移除大头针的自定义视图------------
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view{
[self removeCustomAnnotation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
CoreLocation框架的使用(iOS5之后不再使用)
- CoreLocation框架使用须知:
- CoreLocation框架中所有数据类型的前缀都是CL
- CoreLocation中使用CLLocationManager对象来做用户定位
- 地理编码,反地理编码
//地理编码.根据给定的位置(通常是地名)确定地理坐标
//反地理编码:根据给定的地理位置,确定位置信息(街道,门牌)
#import "SecondViewController.h"
//引入定位头文件
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface SecondViewController ()
@property (nonatomic, strong) CLGeocoder *geocoder;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
//初始化编码对象
_geocoder = [[CLGeocoder alloc]init];
// [self getCoordinateByAddress:@"北京市"];
[self getAddressByLatLong:39.9200225351 Longitude:116.3968733177];
}
#pragma mark----地理编码------------
- (void)getCoordinateByAddress:(NSString *)address{
[self.geocoder geocodeAddressString:address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
//获取第一个地标,地标中存储了详细的地址信息(一个地名可能搜索出多个地址)
CLPlacemark *placemark = [placemarks firstObject];
//获取位置
CLLocation *location = placemark.location;
//获取区域
CLRegion *region = placemark.region;
//地名
NSString *name = placemark.name;
//街道
// NSString *thoroughFare = placemark.thoroughfare;
// //街道相关信息
// NSString *subthoroughFare = placemark.subThoroughfare;
// //城市
// NSString *locatity = placemark.locality;
// //州
// NSString *administrativeArea = placemark.administrativeArea;
//其他行政区信息
NSString *subadministrativeArea = placemark.subAdministrativeArea;
//邮编
// NSString *postalCode = placemark.postalCode;
// //国家编码
// NSString *ISOcountryCode = placemark.ISOcountryCode;
//国家
// NSString *country = placemark.country;
//水源
// NSString *inlandWater = placemark.inlandWater;
//海洋
// NSString *ocean = placemark.ocean;
//关联或者利益相关的地标
// NSArray *areasOfInterest = placemark.areasOfInterest;
// NSDictionary *dic = placemark.addressDictionary;
NSLog(@"位置%@,区域%@,详细信息%@,name%@",location,region,subadministrativeArea,name);
}];
}
#pragma mark----地理编码确定两个城市------------
- (void)Location_2{
//地理编码一次只能定位一个城市,可通过嵌套形式实现定位多个地名
[self.geocoder geocodeAddressString:@"北京市" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
//获取地标
CLPlacemark *placemake = [placemarks firstObject];
MKPlacemark *clplacemark = [[MKPlacemark alloc]initWithPlacemark:placemake];
//嵌套使用
[self.geocoder geocodeAddressString:@"石家庄" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
//获取地标
CLPlacemark *placemake1 = [placemarks firstObject];
MKPlacemark *clplacemark1 = [[MKPlacemark alloc]initWithPlacemark:placemake1];
MKMapItem *mapitem = [[MKMapItem alloc]initWithPlacemark:clplacemark];
MKMapItem *mapitem1 = [[MKMapItem alloc]initWithPlacemark:clplacemark1];
//字典中放一个地图类型
/*
MKMapTypeStandard,普通地图
MKMapTypeSatellite,卫星云图
MKMapTypeHybrid,普通地图覆盖于卫星云图之上
MKMapTypeSatelliteFlyover 地形和建筑物的三维模型
MKMapTypeHybridFlyover 显示道路和附加元素的Flyover
*/
NSDictionary *option = @{MKLaunchOptionsMapTypeKey:@(MKMapTypeStandard)};
[MKMapItem openMapsWithItems:@[mapitem, mapitem1] launchOptions:option];
}];
}];
}
#pragma mark---反地理编码---------
- (void)getAddressByLatLong:(CLLocationDegrees) latitude Longitude:
(CLLocationDegrees) longitude{
//初始化位置信息
CLLocation *location = [[CLLocation alloc]initWithLatitude:latitude longitude:longitude];
[self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
CLPlacemark *placeMark = [placemarks firstObject];
MKPlacemark *clplacemark1 = [[MKPlacemark alloc]initWithPlacemark:placeMark];
MKMapItem *mapitem = [[MKMapItem alloc]initWithPlacemark:clplacemark1];
MKMapItem *mapitem1 = [[MKMapItem alloc]initWithPlacemark:clplacemark1];
//字典中放一个地图类型
NSDictionary *option = @{MKLaunchOptionsMapTypeKey:@(MKMapTypeStandard)};
[MKMapItem openMapsWithItems:@[mapitem, mapitem1] launchOptions:option];
// NSLog(@"%@",placeMark.addressDictionary);
}];
}
- 计算两地之间距离
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()
@property (nonatomic,strong)CLLocationManager *locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建位置管理器
CLLocationManager *locationManager=[[CLLocationManager alloc]init];
self.locationManager=locationManager;
//判断当前设备版本是否大于或等于8.0
if ([UIDevice currentDevice].systemVersion.floatValue >=8.0) {
//持续授权
//[locationManager requestAlwaysAuthorization];
//使用期间授权
[locationManager requestWhenInUseAuthorization];
}
//开始定位
[locationManager startUpdatingLocation];
//比较两点距离
[self compareDistance];
}
//比较两地之间距离(直线距离)
- (void)compareDistance{
//北京
CLLocation *location1=[[CLLocation alloc]initWithLatitude:39.9 longitude:116.3];
//郑州
CLLocation *location2=[[CLLocation alloc]initWithLatitude:34.44 longitude:113.42];
//比较郑州距离北京的距离
/*
distanceFromLocation:用户当前位置
*/
CLLocationDistance locationDistance=[location1 distanceFromLocation:location2];
//单位是m/s 所以这里需要除以1000
NSLog(@"郑北的距离为:%f",locationDistance/1000);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
- 位置管理器
#import "ForthViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ForthViewController ()<CLLocationManagerDelegate>//遵循协议
//声明位置管理属性
@property (nonatomic, strong)CLLocationManager *locationManager;
//保存获取到的位置信息
@property (nonatomic, strong) CLLocation *checkinLocation;
@end
@implementation ForthViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc]init];
//判断你是否打开定位服务
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"定位服务尚未打开,请开启");
return;
}
/*
[CLLocationManager authorizationStatus]指的是当前应用的定位服务授权状态,返回枚举类型
kCLAuthorizationStatusNotDetermined:用户尚未做出决定是否启用定位服务
kCLAuthorizationStatusRestricted:没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权
kCLAuthorizationStatusDenied:用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态
kCLAuthorizationStatusAuthorizedAlways:应用获得授权可以一直使用定位服务,即使应用不在使用状态
kCLAuthorizationStatusAuthorizedWhenInUse:使用此应用过程中允许访问定位服务
*/
//如果没有授权定位服务,就请求用户授权
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
#pragma mark--- ---在info.plist中添加下边两个字段单独拿中的任一个:
/*
①NSLocationWhenInUseUsageDescription YES
②NSLocationAlwaysUsageDescription YES
如果两个同时添加,则默认为第一个,但如果只添加第二个
*/
[self.locationManager requestAlwaysAuthorization];//请求前台和后台定位
}//如果被授权
else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways){
//设置代理
self.locationManager.delegate = self;
//定位精度
/*
kCLLocationAccuracyBestForNavigation;
kCLLocationAccuracyBest;最精确
kCLLocationAccuracyNearestTenMeters;十米误差
kCLLocationAccuracyHundredMeters;百米误差
kCLLocationAccuracyKilometer;千米误差
kCLLocationAccuracyThreeKilometers;三千米误差
*/
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//定位频率(每隔多少米定位一次,单位:米)
CLLocationDistance distance = 10.0;
self.locationManager.distanceFilter = distance;
//启动定位符
[self.locationManager startUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
// 取出位置
CLLocation *location = [locations firstObject];
// 位置坐标
CLLocationCoordinate2D coordinate = location.coordinate;
NSLog(@"经度:%f,纬度:%f,海拔:%f,航向:%f,行走速度:%f",coordinate.longitude,coordinate.latitude,location.altitude,location.course,location.speed);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
定位系统在模拟器上不能显示,可真机测试