iOS中的地图,有两种:
1、苹果自带的地图SDK,(MKMapKit)但是它在中国使用时,内部还是使用的是高德地图。(高德为苹果在中国的地图合作方)
2、第三方地图SDK (例如:高德的地图SDK,( MAMapKit)、百度地图SDK(BMapKit))。
使用苹果自带的地图MKMapKit,需要导入框架:MapKit.frameworks、CoreLocation.framework
定位
目前iOS定位方式有三种:基站 WIFI A-GPS
基站:省电、定位不精准(大概位置)
WIFI:和基站差不多,比基站更费电、定位不精准(大概位置)
A-GPS:苹果改良了直接使用GPS,先使用基站和WIFI获得大概位置,然后苹果自动推荐当前区域的离你位置最近的GPS卫星,这样就不用再搜索卫星了,直接就可以使用了。费电、定位精准。
打开定位,在iOS8以前自动弹出对话框。在iOS8之后,必须在info.plist文件中添加一行 NSLocationAlwaysUsageDescription 或者
NSLocationWhenInUseUsageDescription
注意:一定要写对,不然不会弹出提示。
区别:
WhenInUse是应用在前台的时候可以搜到更新的位置信息,Always是除了应用在前台,应用在后台(suspend或terminated)都可以获取到更新的位置数据 ,根据需要,按需去申请权限。 |
图:
代码:
<span style="color:#333333;">#import "AZViewController.h" #import <MapKit/MapKit.h> @interface AZViewController ()<MKMapViewDelegate,CLLocationManagerDelegate> { MKMapView *_mapView; CLLocationManager *_manager; } @end @implementation AZViewController - (void)viewDidLoad { [super viewDidLoad]; /** iOS中的地图,有两种: 1、苹果自带的地图SDK,(MKMapKit)但是它在中国使用的时高德地图。 2、2、第三方地图SDK (例如:高德的地图SDK,( MAMapKit)、百度地图SDK(BMapKit))。 使用方法: 1、 使用苹果自带的地图MKMapKit,需要导入框架:MapKit.frameworks、CoreLocation.framework */ [self useMkMapKit]; } -(void)useMkMapKit { _mapView=[[MKMapView alloc] initWithFrame:self.view.bounds]; // 地图类型,默认为基本 // MKMapTypeSatellite 卫星 // MKMapTypeStandard 基本 // MKMapTypeHybrid 混合 _mapView.mapType=MKMapTypeStandard; [self.view addSubview:_mapView]; UILongPressGestureRecognizer *longPress=[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:) ]; [_mapView addGestureRecognizer:longPress]; /** 定位 目前iOS定位方式有三种: 基站 WIFI A-GPS 基站:省电、定位不精准(大概位置) WIFI:和基站差不多,比基站更费电、定位不精准(大概位置) A-GPS:苹果改良了直接使用GPS,先使用基站和WIFI获得大概位置,然后苹果自动推荐当前区域的离你位置最近的GPS卫星,这样就不用再搜索卫星了,直接就可以使用了。费电、定位精准。 打开定位,在iOS8以前自动弹出对话框。在iOS8之后,必须在info.plist文件中添加一行 NSLocationAlwaysUsageDescription */ //获取定位管理对象 _manager=[[CLLocationManager alloc] init]; // </span><span style="color:#ff0000;">//ios 8 必须加上 // [_manager requestAlwaysAuthorization];</span><span style="color:#333333;"> //精准度 /* kCLLocationAccuracyBestForNavigation 导航精准(导航使用) kCLLocationAccuracyBest 普通精准 kCLLocationAccuracyNearestTenMeters 误差十米 kCLLocationAccuracyHundredMeters 误差百米 kCLLocationAccuracyKilometer 误差千米 kCLLocationAccuracyThreeKilometers 误差三千米 */ _manager.desiredAccuracy=kCLLocationAccuracyBest; //定位距离过滤器,超过10米,才重新定位一次 _manager.distanceFilter=10; //设置代理 _manager.delegate=self; //开始定位 [_manager startUpdatingLocation]; //开始方向定位 [_manager startUpdatingHeading]; //显示当前用户的位置 _mapView.showsUserLocation=YES; } //长按添加大头针 -(void)longPress:(UILongPressGestureRecognizer *)longPress { if (longPress.state!=UIGestureRecognizerStateBegan) { return; } //坐标 CGPoint point=[longPress locationInView:_mapView]; //转成经纬度 CLLocationCoordinate2D coordinate=[_mapView convertPoint:point toCoordinateFromView:_mapView]; //地图中心经纬度 //_mapView.centerCoordinate=coordinate; //缩放比例 MKCoordinateSpan span=MKCoordinateSpanMake(0.5, 0.5); //要显示的区域 MKCoordinateRegion regin=MKCoordinateRegionMake(coordinate, span); //地图显示一个区域 [_mapView setRegion:regin animated:YES]; /** 添加大头针 1:苹果自带框架下有一个大头针数据类,它可以显示标题,副标题。 2: 自定义大头针。 */ // 第一种大头针(系统自带) //添加一个标签/大头针 (数据类) MKPointAnnotation *anno=[[MKPointAnnotation alloc] init]; //标题 anno.title=@"KFC"; //副标题 anno.subtitle=@"地址:海淀黄庄"; //显示位置 anno.coordinate=coordinate; //添加到地图上 [_mapView addAnnotations:@[anno]]; //第二种,自定义大头针,使用代理 _mapView.delegate=self; } #pragma mark -- 自定义大头针 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation { if([annotation isKindOfClass:[_mapView.userLocation class]]) { return nil; } static NSString *idn=@"ID"; MKPinAnnotationView *annoView=(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:idn]; if (!annoView) { annoView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:idn]; } //显示详情面板 annoView.canShowCallout=YES; //颜色 annoView.pinColor=MKPinAnnotationColorPurple; //拖拽 annoView.draggable=YES; //动画效果 annoView.animatesDrop=YES; //添加左视图 UIView *leftview=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)]; leftview.backgroundColor=[UIColor redColor]; annoView.leftCalloutAccessoryView=leftview; //添加右视图 UIButton *btn=[UIButton buttonWithType:UIButtonTypeDetailDisclosure]; annoView.rightCalloutAccessoryView=btn; /** 添加响应事件 */ return annoView; } #pragma mark -- 实现定位协议 //定位成功 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { //拿到定位的位置 CLLocation *location=[locations lastObject]; //缩放比例 MKCoordinateSpan span=MKCoordinateSpanMake(0.1, 0.1); MKCoordinateRegion region=MKCoordinateRegionMake(location.coordinate, span); [_mapView setRegion:region animated:YES]; //停止定位 [manager stopUpdatingLocation]; } -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"定位失败"); } //方向定位成功 -(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { NSLog(@"%f",newHeading.trueHeading); } -(BOOL)prefersStatusBarHidden { return YES; } @end </span>
更多使用方法,请参考高德开发者平台 http://lbs.amap.com
代码:
#import "AZViewController.h" #import "AZTest.h" #import <MAMapKit/MAMapKit.h> #import <AMapSearchKit/AMapSearchAPI.h> @interface AZViewController ()<MAMapViewDelegate,AMapSearchDelegate> { MAMapView *_mapview; AMapSearchAPI *_search; } @end @implementation AZViewController - (void)viewDidLoad { [super viewDidLoad]; [MAMapServices sharedServices].apiKey=@"372fd6b384ecb49675eaa48440d86a08"; _mapview =[[MAMapView alloc] initWithFrame:self.view.bounds]; //地图类型 多了夜景模式 MAMapTypeStandardNight _mapview.mapType=MAMapTypeStandard; //是否显示罗盘 _mapview.showsCompass=YES; //是否显示交通情况(实时的) _mapview.showTraffic=NO; //设置代理 _mapview.delegate=self; # if 0 //画线 [self makeLine]; //花园 [self makeYuan]; #endif #if 0 //POI搜索 [self searchPOI:@"俏江南"]; #endif #if 0 //正向地理编码 [self getCode:@"王府井"]; #endif #if 0 //逆向地理编码 [self getNameByLatitude:39.990459 andLongTitude:116.481476]; #endif #if 0 //导航 [self navSearch]; #endif #if 1 //定位 [self locationPos]; #endif [self.view addSubview:_mapview]; } #pragma mark -- 定位 -(void)locationPos { _mapview.showsUserLocation=YES; //地图跟着位置移动 [_mapview setUserTrackingMode: MAUserTrackingModeFollow animated:YES]; } -(void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation { if(updatingLocation) { //取出当前位置的坐标 NSLog(@"latitude : %f,longitude: %f",userLocation.coordinate.latitude,userLocation.coordinate.longitude); } } #pragma mark -- 导航 -(void)navSearch { //初始化检索对象 _search = [[AMapSearchAPI alloc] initWithSearchKey:@"372fd6b384ecb49675eaa48440d86a08" Delegate:self]; //构造AMapNavigationSearchRequest对象,配置查询参数 AMapNavigationSearchRequest *naviRequest= [[AMapNavigationSearchRequest alloc] init]; naviRequest.searchType = AMapSearchType_NaviDrive; naviRequest.requireExtension = YES; //起点经纬度 naviRequest.origin = [AMapGeoPoint locationWithLatitude:39.994949 longitude:116.447265 ]; //目的地经纬度 naviRequest.destination = [AMapGeoPoint locationWithLatitude:39.990459 longitude:116.481476]; //发起路径搜索 [_search AMapNavigationSearch: naviRequest]; } //实现路径搜索的回调函数 - (void)onNavigationSearchDone:(AMapNavigationSearchRequest *)request response:(AMapNavigationSearchResponse *)response { if(response.route == nil) { return; } //拿到第一个方案 AMapRoute *route=response.route; //第一个方案的路线 AMapPath *path=route.paths[0]; NSMutableArray *coordinateArray=[[NSMutableArray alloc] initWithCapacity:path.steps.count]; //遍历这个方案中的路段 for(AMapStep *step in path.steps) { NSArray *pointArray=[step.polyline componentsSeparatedByString:@";"]; for (NSString *str in pointArray) { [coordinateArray addObject:str]; } } CLLocationCoordinate2D coordinate[coordinateArray.count]; //遍历坐标字符串 for (int i = 0; i < coordinateArray.count; i++) { //经纬度字符串 116,14 NSString* pointStr = coordinateArray[i]; NSArray* pointArray = [pointStr componentsSeparatedByString:@","]; //取得经纬度 coordinate[i].longitude = [pointArray[0] floatValue]; coordinate[i].latitude = [pointArray[1] floatValue]; } MAPolyline* polyline = [MAPolyline polylineWithCoordinates:coordinate count:coordinateArray.count]; [_mapview addOverlay:polyline]; } #pragma mark -- 逆向地理编码 (根据经纬度获取地名) -(void)getNameByLatitude:(float)latitude andLongTitude:(float)longtitud { //初始化检索对象 _search = [[AMapSearchAPI alloc] initWithSearchKey:@"372fd6b384ecb49675eaa48440d86a08" Delegate:self]; //构造AMapReGeocodeSearchRequest对象,location为必选项,radius为可选项 AMapReGeocodeSearchRequest *regeoRequest = [[AMapReGeocodeSearchRequest alloc] init]; regeoRequest.searchType = AMapSearchType_ReGeocode; regeoRequest.location = [AMapGeoPoint locationWithLatitude:latitude longitude:longtitud]; regeoRequest.radius = 10000; regeoRequest.requireExtension = YES; //发起逆地理编码 [_search AMapReGoecodeSearch: regeoRequest]; } //实现逆地理编码的回调函数 - (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response { if(response.regeocode != nil) { AMapReGeocode *regeocode=response.regeocode; NSLog(@"%@",regeocode.formattedAddress); } } #pragma mark -- 正向地理编码(根据地名获取经纬度) -(void)getCode:(NSString *)name { //初始化检索对象 _search = [[AMapSearchAPI alloc] initWithSearchKey:@"372fd6b384ecb49675eaa48440d86a08" Delegate:self]; //构造AMapGeocodeSearchRequest对象,address为必选项,city为可选项 AMapGeocodeSearchRequest *geoRequest = [[AMapGeocodeSearchRequest alloc] init]; geoRequest.searchType = AMapSearchType_Geocode; geoRequest.address = name; geoRequest.city = @[@"beijing"]; //发起正向地理编码 [_search AMapGeocodeSearch: geoRequest]; } //实现正向地理编码的回调函数 - (void)onGeocodeSearchDone:(AMapGeocodeSearchRequest *)request response:(AMapGeocodeSearchResponse *)response { if(response.geocodes.count == 0) { return; } for ( AMapGeocode *deoCode in response.geocodes) { MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init]; pointAnnotation.coordinate = CLLocationCoordinate2DMake(deoCode.location.latitude, deoCode.location.longitude); pointAnnotation.title = deoCode.district; [_mapview addAnnotations:@[pointAnnotation]]; } } #pragma mark -- POI搜索 (也称兴趣点搜索) -(void)searchPOI:(NSString *)keyWords { //初始化检索对象 _search = [[AMapSearchAPI alloc] initWithSearchKey:@"372fd6b384ecb49675eaa48440d86a08" Delegate:self]; //创建一个请求 //构造AMapPlaceSearchRequest对象,配置关键字搜索参数 AMapPlaceSearchRequest *poiRequest = [[AMapPlaceSearchRequest alloc] init]; poiRequest.searchType = AMapSearchType_PlaceKeyword; poiRequest.keywords = keyWords; //搜索哪个城市,数组表示可以搜索多个城市 poiRequest.city = @[@"beijing"]; poiRequest.requireExtension = YES; //发起POI搜索 [_search AMapPlaceSearch: poiRequest]; } //POI回调 -(void)onPlaceSearchDone:(AMapPlaceSearchRequest *)request response:(AMapPlaceSearchResponse *)response { //遍历数组 for (AMapPOI *poi in response.pois) { MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init]; pointAnnotation.coordinate = CLLocationCoordinate2DMake(poi.location.latitude, poi.location.longitude); pointAnnotation.title = poi.name; pointAnnotation.subtitle = poi.address; [_mapview addAnnotations:@[pointAnnotation]]; } } -(MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation { if ([annotation isKindOfClass:[MAPointAnnotation class]]) { static NSString *pointReuseIndetifier = @"pointReuseIndetifier"; MAPinAnnotationView*annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier]; if (annotationView == nil) { annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier]; } annotationView.canShowCallout= YES; //设置气泡可以弹出,默认为NO annotationView.animatesDrop = YES; //设置标注动画显示,默认为NO annotationView.draggable = YES; //设置标注可以拖动,默认为NO annotationView.pinColor = MAPinAnnotationColorPurple; return annotationView; } return nil; } #pragma mark -- 画线 -(void)makeLine { //构造折线数据对象 CLLocationCoordinate2D commonPolylineCoords[4]; commonPolylineCoords[0].latitude = 39.832136; commonPolylineCoords[0].longitude = 116.34095; commonPolylineCoords[1].latitude = 39.832136; commonPolylineCoords[1].longitude = 116.42095; commonPolylineCoords[2].latitude = 39.902136; commonPolylineCoords[2].longitude = 116.42095; commonPolylineCoords[3].latitude = 39.902136; commonPolylineCoords[3].longitude = 116.44095; //构造折线对象 MAPolyline *commonPolyline = [MAPolyline polylineWithCoordinates:commonPolylineCoords count:4]; //在地图上添加折线对象 [_mapview addOverlay: commonPolyline]; } #pragma mark -- 画圆 -(void)makeYuan { //构造圆 MACircle *circle = [MACircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(39.952136, 116.50095) radius:5000]; //在地图上添加圆 [_mapview addOverlay: circle]; } #pragma mark -- 手动创建覆盖物,这里才是真正的创建了覆盖物(折线,画园) - (MAOverlayView *)mapView:(MAMapView *)mapView viewForOverlay:(id <MAOverlay>)overlay { //判断是折线 if ([overlay isKindOfClass:[MAPolyline class]]) { //折线类 MAPolylineView *polylineView = [[MAPolylineView alloc] initWithPolyline:overlay]; //线宽 polylineView.lineWidth = 10.f; //颜色 polylineView.strokeColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.6]; //连接类型 polylineView.lineJoinType = kMALineJoinRound; //端点类型 polylineView.lineCapType = kMALineCapRound; return polylineView; } else if ([overlay isKindOfClass:[MACircle class]]) { MACircleView *circleView = [[MACircleView alloc] initWithCircle:overlay]; circleView.lineWidth = 5.f; circleView.strokeColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:0.8]; circleView.fillColor = [UIColor colorWithRed:1.0 green:0.8 blue:0.0 alpha:0.8]; circleView.lineDash = YES; return circleView; } return nil; } #pragma mark -- 隐藏状态栏 -(BOOL)prefersStatusBarHidden { return YES; } @end
折线、画圆 POI
导航