#import <CoreLocation/CoreLocation.h>
typedef struct {
CLLocationDegreeslatitude;// 纬度
CLLocationDegreeslongitude;// 经度
} CLLocationCoordinate2D;
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>
@property(nonatomic,strong)CLLocationManager *mgr;
@end
@implementation ViewController
#pragma mark - 懒加载
- (CLLocationManager *)mgr
{
if (_mgr == nil) {
// 1.创建定位管理者
_mgr = [[CLLocationManager alloc] init];
// 2.设置代理(我们得通过代理获取用户的位置信息)
_mgr.delegate = self;
// 3.位置间隔之后重新定位
_mgr.distanceFilter = 10;
// 4.定位的精确度
_mgr.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
return _mgr;
}
- (void)viewDidLoad {
[super viewDidLoad];
/*
// 1.创建定位管理者
CLLocationManager *mgr = [[CLLocationManager alloc] init];
// 2.设置代理
mgr.delegate = self;
*/
// 3.开始定位
[self.mgr startUpdatingLocation];
// 4.计算两个经纬度之间的距离
[self countDistance];
}
/**
* 计算两个经纬度之间的距离
*/
- (void)countDistance
{
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:23.23 longitude:113.33];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:40.06 longitude:116.39];
CLLocationDistance distance = [location1 distanceFromLocation:location2];
NSLog(@"%f", distance);
}
/**
* 定位到用户的位置会调用该方法(并且该方法调用非常频繁)
*
* @param locations 存放着定位的所有位置
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// 1.获取用户位置的对象
CLLocation *location = [locations lastObject];
CLLocationCoordinate2D coordinate = location.coordinate;
NSLog(@"纬度:%f 经度:%f", coordinate.latitude, coordinate.longitude);
// 2.停止定位
[manager stopUpdatingLocation];
}
CLGeocoder
补充.
1.CLPlacemark的addressDictionary属性 遍历字典数据
addressDictionary enumerateKeysAndObjectsUsingBlock
2.block是在主线程调用,所以可以直接在block刷新UI
name : 地名
thoroughfare : 街道
ubThoroughfare : 街道相关信息,例如门牌等
locality : 城市
subLocality : 城市相关信息,例如标志性建筑
administrativeArea : 直辖市
subAdministrativeArea : 其他行政区域信息
postalCode : 邮编
ISOcountryCode : 国家编码
country; : 国家
inlandWater : 水源、湖泊
ocean; : 海洋
areasOfInterest : 关联的或利益相关的地标
// 地理编码
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 如果解析有错误,或者解析出的数组个数为0,直接返回
if (placemarks.count == 0 || error) return ;
// 遍历所有的地标对象
for (CLPlacemark *pm in placemarks) {
// 取出用户的位置信息
CLLocation *location = pm.location;
// 取出用户的经纬度
CLLocationCoordinate2D coordinate = location.coordinate;
// 将信息设置到界面上
self.latitude.text = [NSString stringWithFormat:@"%.2f", coordinate.latitude];
self.longitude.text = [NSString stringWithFormat:@"%.2f", coordinate.longitude];
self.result.text = pm.name;
}
}];
反地理编码:
// 2.反地理编码
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude.floatValue longitude:longitude.floatValue];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
// 如果有错误,或者解析出来的地址数量为0
if (placemarks.count == 0 || error) return ;
// 取出地标,就可以取出地址信息,以及CLLocation对象
CLPlacemark *pm = [placemarks firstObject];
#warning 注意:如果是取出城市的话,需要判断locality属性是否有值(直辖市时,该属性为空)
if (pm.locality) {
self.resultLabel.text = pm.locality;
} else {
self.resultLabel.text = pm.administrativeArea;
}
}];
MapKit 框架的使用
#import <MapKit/MapKit.h>
typedef struct {
CLLocationCoordinate2D center; //区域的中心点位置
MKCoordinateSpan span;//区域的跨度
} MKCoordinateRegion;
typedef struct {
CLLocationDegrees latitudeDelta; //纬度跨度
CLLocationDegrees longitudeDelta; //经度跨度
} MKCoordinateSpan;
// 显示地图的View
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 设置代理
self.mapView.delegate = self;
// 跟踪用户的位置
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
// 设置地图类型
self.mapView.mapType = MKMapTypeSatellite;
}
/**
* 定位到用户的位置会执行该方法
*
* @param userLocation 大头针模型
*/
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// 取出用户的位置
CLLocationCoordinate2D coordinate = userLocation.location.coordinate;
NSLog(@"纬度:%f 经度:%f", coordinate.latitude, coordinate.longitude);
// 改变大头针显示的内容(通过改变大头针模型的属性)
// userLocation.title = @"广州市";
// userLocation.subtitle = @"广东省广州市天河区";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *location = userLocation.location;
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks.count == 0 || error) return;
CLPlacemark *pm = [placemarks firstObject];
if (pm.locality) {
userLocation.title = pm.locality;
} else {
userLocation.title = pm.administrativeArea;
}
userLocation.subtitle = pm.name;
}];
}
#import "ViewController.h"
#import <MapKit/MapKit.h>
#define kLatitudeDelta 0.002703
#define kLongitudeDelta 0.001717
@interface ViewController () <MKMapViewDelegate>
// 显示地图的View
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
/**
* 点击之后回到用户的位置
*/
- (IBAction)backToUserLocation;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 设置代理
self.mapView.delegate = self;
// 跟踪用户的位置
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
// 设置地图类型
// self.mapView.mapType = MKMapTypeSatellite;
}
/**
* 定位到用户的位置会执行该方法
*
* @param userLocation 大头针模型
*/
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// 取出用户的位置
CLLocationCoordinate2D coordinate = userLocation.location.coordinate;
NSLog(@"纬度:%f 经度:%f", coordinate.latitude, coordinate.longitude);
// 设置mapView显示的中心位置
// [mapView setCenterCoordinate:coordinate animated:YES];
// 设置mapView的显示区域
MKCoordinateSpan span = MKCoordinateSpanMake(kLatitudeDelta, kLongitudeDelta);
MKCoordinateRegion region = MKCoordinateRegionMake(coordinate, span);
[mapView setRegion:region animated:YES];
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
MKCoordinateRegion region = mapView.region;
CLLocationCoordinate2D center = region.center;
MKCoordinateSpan span = region.span;
NSLog(@"纬度:%f 经度:%f", center.latitude, center.longitude);
NSLog(@"纬度跨度:%f 经度跨度:%f", span.latitudeDelta, span.longitudeDelta);
}
// 点击按钮回到用户当前的位置
- (IBAction)backToUserLocation {
// 地图的跨度
MKCoordinateSpan span = MKCoordinateSpanMake(kLatitudeDelta, kLongitudeDelta);
// 地图的显示区域
MKCoordinateRegion region = MKCoordinateRegionMake(self.mapView.userLocation.location.coordinate, span);
// 设置地图中心位置为用户的当前位置
// [self.mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate animated:YES];
// 设置地图的显示区域
[self.mapView setRegion:region animated:YES];
}
// 2.通过判断是否有该方法来判断是否需要请求requestAlwaysAuthorization授权
if ([self.mgr respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[self.mgr requestAlwaysAuthorization];
}
大头针的基本操作
#import <MapKit/MapKit.h>
@interface MyAnnotation : NSObject <MKAnnotation>
/**坐标位置*/
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
/**标题*/
@property (nonatomic, copy) NSString *title;
/**子标题*/
@property (nonatomic, copy) NSString *subtitle;
@end
- (void)viewDidLoad {
[super viewDidLoad];
// 1.设置代理
self.mapView.delegate = self;
// 2.跟踪用户的位置
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
// 3.添加两个大头针
MyAnnotation *anno1 = [[MyAnnotation alloc] init];
anno1.coordinate = CLLocationCoordinate2DMake(40.06, 116.39);
anno1.title = @"北京市";
anno1.subtitle = @"中国北京市昌平区";
MyAnnotation *anno2 = [[MyAnnotation alloc] init];
anno2.coordinate = CLLocationCoordinate2DMake(30.23, 120.23);
anno2.title = @"杭州市";
anno2.subtitle = @"浙江省杭州市萧山区";
[self.mapView addAnnotation:anno1];
[self.mapView addAnnotation:anno2];
}
/**
* 定位到用户的位置会调用该方法
*
* @param userLocation 大头针模型对象
*/
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// 设置用户的位置为地图的中心点
[mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.获取用户点击的点
CGPoint point = [[touches anyObject] locationInView:self.view];
// 2.将该点转化成经纬度(地图上的坐标)
CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.view];
// 3.添加大头针
MyAnnotation *anno = [[MyAnnotation alloc] init];
anno.coordinate = coordinate;
anno.title = @"我的位置";
anno.subtitle = @"你猜我在那?";
[self.mapView addAnnotation:anno];
}
自定义大头针
/**
* 在地图上添加一个大头针就会执行该方法
*
* @param annotation 大头针模型对象
*
* @return 大头针的View(返回nil表示默认使用系统, 默认MKAnnotationView是不可见)
*/
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// 1.如果是用户位置的大头针,直接返回nil,使用系统的
if ([annotation isKindOfClass:[MKUserLocation class]]) return nil;
// 2.创建标识
static NSString *ID = @"annoView";
// 3.从缓冲池中取出大头针的View
MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
// 4.如果为nil,则创建
if (annoView == nil) {
annoView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:ID];
// 1.设置标题和子标题可以呼出
annoView.canShowCallout = YES;
// 2.设置大头针的颜色
annoView.pinColor = MKPinAnnotationColorPurple;
// 3.掉落效果
annoView.animatesDrop = YES;
}
// 5.设置大头针的大头针模型
annoView.annotation = annotation;
return annoView;
}
使用苹果内置地图做导航
#import "ViewController.h"
#import <MapKit/MapKit.h>
@interface ViewController ()
// 目的地的输入框
@property (weak, nonatomic) IBOutlet UITextField *destinationField;
/**
* 点击按钮之后开始导航
*/
- (IBAction)navigate;
@end
@implementation ViewController
- (IBAction)navigate {
// 1.拿到用户输入的目的地
NSString *destination = self.destinationField.text;
if (destination.length == 0) {
return;
}
// 2.地理编码
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:destination completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks.count == 0 || error) return ;
// 2.1.取出地理编码出的地标
CLPlacemark *clpm = [placemarks firstObject];
// 2.2.利用CLPlacemark来创建MKPlacemark
MKPlacemark *mkpm = [[MKPlacemark alloc] initWithPlacemark:clpm];
// 2.3.利用MKPlacemark来创建目的地的MKMapItem
MKMapItem *destinationItem = [[MKMapItem alloc] initWithPlacemark:mkpm];
// 2.4.拿到起点的MKMapItem
MKMapItem *sourceItem = [MKMapItem mapItemForCurrentLocation];
// 2.5.开始导航
[self startNavigateWithSourceItem:sourceItem destinationItem:destinationItem];
}];
}
/**
* 开始导航
*
* @param sourceItem 起点的Item
* @param destinationItem 终点的Item
*/
- (void)startNavigateWithSourceItem:(MKMapItem *)sourceItem destinationItem:(MKMapItem *)destinationItem
{
// 1.将起点和终点item放入数组中
NSArray *items = @[sourceItem, destinationItem];
// 2.设置Options参数(字典)
NSDictionary *options = @{
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsMapTypeKey : @(MKMapTypeHybrid),
MKLaunchOptionsShowsTrafficKey : @YES
};
// 3.开始导航
[MKMapItem openMapsWithItems:items launchOptions:options];
}