1 1. 地图 2 1. 获取用户的经纬度(CLLocationManager) 3 创建属性:CLLocationManager *mgr; 4 遵守协议:<CLLocationManagerDelegate> 5 a> 创建定位管理器 6 self.mgr = [[CLLocationManager alloc] init]; 7 b> 设置代理 8 self.mgr.delegate = self; 9 c> 开始定位 10 [self.mgr startUpdatingLocation]; 11 代理方法: 12 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ 13 //获取用户的位置 14 CLLocation *local = [locations firstObject]; 15 //停止定位 16 // [self.mgr stopUpdatingLocation]; 17 CLLocationCoordinate2D coordinate = local.coordinate; 18 NSLog(@"纬度:%f,经度:%f",coordinate.latitude,coordinate.longitude); 19 } 20 2. 计算两个经纬度之间的距离 21 //拿到两个点 22 CLLocation *lcoal1 = [[CLLocation alloc] initWithLatitude:39.54 longitude:116.28]; 23 CLLocation *local2 = [[CLLocation alloc] initWithLatitude:22.27 longitude:113.46]; 24 //开始计算距离 25 CLLocationDistance distance = [local2 distanceFromLocation:lcoal1]; 26 NSLog(@"北京到深圳的距离是:%f",distance); 27 28 3.地理编码与反编码 29 3.1地里编码 30 a> 初始化地理编码类对象 31 CLGeocoder *geo = [[CLGeocoder alloc] init]; 32 b> 通过地址名称,获得地标数组(一个名称,多个地址) 33 //开始地理编码 34 [geo geocodeAddressString:self.addressField.text completionHandler:^(NSArray *placemarks, NSError *error) { 35 if (placemarks.count == 0 || error) return; 36 37 //获取地标 38 NSLog(@"%lu",(unsigned long)placemarks.count); 39 NSString *temp = @""; 40 for (CLPlacemark *pm in placemarks) { 41 CLLocationCoordinate2D coordinate = pm.location.coordinate; 42 //纬度 coordinate.latitude; 43 //经度 coordinate.longitude; 44 //同名的 多个地址追加 45 temp = [temp stringByAppendingString:[NSString stringWithFormat:@"%@\n",pm.name]]; 46 47 } 48 }]; 49 c> 地标对象(CLPlacemark)封装了经纬度,国家,街道等地址信息 50 CLPlacemark 属性图如下 51 52 CLLocation *location; 53 CLRegion *region; 54 55 56 3.2反地理编码 57 a> 初始化地理编码对象 58 CLGeocoder *geo = [[CLGeocoder alloc] init]; 59 b> 初始化经纬度定位对象(CLLocation) 60 61 CLLocation *local = [[CLLocation alloc] initWithLatitude:[self.latitudeField.text floatValue] longitude:[self.longitudeField.text floatValue]]; 62 c> 传入CLLocation,获得地标 63 64 [geo reverseGeocodeLocation:local completionHandler:^(NSArray *placemarks, NSError *error) { 65 //获取地标 66 CLPlacemark *pm = [placemarks firstObject]; 67 self.addressDetail.text = pm.name; 68 69 }]; 70 4.MapKit地图的基本展示 71 需要: 72 1. 导入头文件 #import <MapKit/MapKit.h> 73 2. 导入framework MapKit 74 4.1简单的地图显示 75 a>自定义-简单的地图展示 76 MKMapView *mapView = [[MKMapView alloc] initWithFrame:self.view.bounds]; 77 self.view = mapView; 78 4.2 Map视图控制器的使用 79 a> 使用视图控制器,遵守协议。使用代理< MKMapViewDelegate> 80 81 IBOutlet MKMapView *mapView; 82 //是否显示用户位置 83 self.mapView.showsUserLocation = YES; 84 //地图类型 85 /** 86 * MKMapTypeStandard = 0, 标准地图 87 MKMapTypeSatellite, 卫星 88 MKMapTypeHybrid 混合地图 89 */ 90 self.mapView.mapType = MKMapTypeHybrid; 91 92 b> 通过代理方法,更新用户位置 93 -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{ 94 95 //设置地图展示范围setRegion : coordinate & span 96 [self.mapView setRegion:MKCoordinateRegionMake(userLocation.location.coordinate, MKCoordinateSpanMake(5.067069, 3.835159))]; 97 // 通过经纬度获得地标。 98 CLGeocoder *geo = [[CLGeocoder alloc] init]; 99 [geo reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray *placemarks, NSError *error) { 100 //获取地标 101 CLPlacemark *pm = [placemarks firstObject]; 102 userLocation.title = pm.country; 103 userLocation.subtitle = pm.name; 104 }]; 105 106 } 107 108 /** 109 * 当地图显示的范围发生改变的时候 110 * 111 */ 112 -(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ 113 114 NSLog(@"维度的跨度:%f,经度的跨度:%f",mapView.region.span.latitudeDelta,mapView.region.span.longitudeDelta); 115 } 116 4.3 IOS8.0+ 中的地图设置 117 判断设备系统版本 118 if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { 119 [self.mgr requestAlwaysAuthorization]; 120 } 121 122 123 //跟踪用户位置(在iOS8中,地图会自动设置一个合适的显示范围) 124 self.mapView.userTrackingMode = MKUserTrackingModeFollow; 125 5.大头针 126 在IOS8中,显示用户的大头针,需要先定位 127 128 5.1在地图添加大头针 129 a> 使用Map视图控制器 130 b> 创建大头针,设置相关属性 131 132 MyAnnotation *anno = [[MyAnnotation alloc] init]; 133 //设置大头针的title 134 anno.title = @"北京"; 135 anno.subtitle = @"中国"; 136 //设置添加大头针的位置 137 anno.coordinate = CLLocationCoordinate2DMake(39.54, 116.28); 138 139 c> 将大头针显示到地图视图 140 [self.mapView addAnnotation:anno]; 141 //添加多个大头针 142 [self.mapView addAnnotations:@[anno,anno1]]; 143 144 5.2 touch每点击地图添加大头针 145 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 146 147 //1.获取屏幕上的点 148 CGPoint p = [[touches anyObject] locationInView:self.mapView]; 149 //2.把点转化为经纬度 150 CLLocationCoordinate2D coordinate = [self.mapView convertPoint:p toCoordinateFromView:self.mapView]; 151 152 //3.添加大头针 153 MyAnnotation *anno = [[MyAnnotation alloc] init]; 154 155 //设置大头针的title 156 anno.title = @"北京"; 157 anno.subtitle = @"中国"; 158 159 //设置添加大头针的位置 160 anno.coordinate = coordinate; 161 162 [self.mapView addAnnotation:anno]; 163 164 } 165 166 5.3 大头针触发的代理方法 167 -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{ 168 // 如果是系统添加大头针的操作,则返回nil,仍然是系统的 圆点大头针 169 // 如果是自定义的大头针。继续执行 170 if ([annotation isKindOfClass:[MKUserLocation class]]) { 171 return nil; 172 } 173 174 //如果返回空,就是用系统自带的大头针 175 // return nil; 176 177 //这里是 自定义大头针 的设置 178 static NSString *ID = @"anno"; 179 MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID]; 180 181 if (annotationView == nil) { 182 annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID]; 183 184 } 185 186 //设置大头针的颜色 187 annotationView.pinColor = MKPinAnnotationColorPurple; 188 189 //设置大头针的动画 190 annotationView.animatesDrop = YES; 191 192 // 返回大头针 视图 193 return annotationView; 194 195 } 196 5.4 自定义大头针的视图 197 思路:每次在对大头针操作的时候 会触发代理方法,代理方法 返回一个大头针的视图对象。如果 重新定义一个大头针对象返回,则可以 达到自定义大头针显示的目的。 198 a> 定义类,继承大头针类 199 b> 重写类属性 200 c> 在viewForAnnotation代理方法中创建自定义大头针类对象 201 // 添加大头针后 执行这个方法 202 -(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{ 203 204 // 可以同过遍历views,设置初始位置,设置动画 205 for (UIView *view2 in views) { 206 CGRect rec = view2.frame; 207 view2.frame = CGRectMake(rec.origin.x, 0, rec.size.width, rec.size.height); 208 [UIView animateWithDuration:1.0 animations:^{ 209 210 view2.frame = rec; 211 }]; 212 213 } 214 215 } 216 思路2:直接在代理方法中,给大头针设置图片img 217 annotationView.image = [UIImage imageNamed:@"category_3"]; 218 6.使用系统自带导航 219 流程: 220 用户输入需要去的位置, 221 通过位置计算地标,地标转地图标记,地图标记转地图item。 222 获取当前用户的item。开启导航。 223 224 a> 初始化地理编码类 225 CLGeocoder *geo = [[CLGeocoder alloc] init]; 226 b> 通过地址拿到地标 227 [geo geocodeAddressString:self.destinationField.text completionHandler:^(NSArray *placemarks, NSError *error) { 228 // 需要处理没有 地标的情况 229 if (placemarks.count == 0 || error) return; 230 //地理编码后拿到地标 231 CLPlacemark *pm = [placemarks firstObject]; 232 233 //创建MKPlacemark 234 MKPlacemark *mkp = [[MKPlacemark alloc] initWithPlacemark:pm]; 235 //目的地Item 236 MKMapItem *destinationItem = [[MKMapItem alloc] initWithPlacemark:mkp]; 237 238 //用户当前的item 239 MKMapItem *currentItem = [MKMapItem mapItemForCurrentLocation]; 240 241 242 //2.开启导航 243 NSDictionary *option = @{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,/*驾车*/ 244 MKLaunchOptionsMapTypeKey:@0, /*地图类型 0标准,1卫星,2混合*/ 245 MKLaunchOptionsShowsTrafficKey:@NO /*交通状况*/ 246 247 }; 248 249 [MKMapItem openMapsWithItems:@[currentItem,destinationItem] launchOptions:option]; 250 }]; 251 252 6.1自定义画线 253 通过目标位置,用户当前位置行程画线 254 在上节中已经有了获得目标位置item的方法 255 info : NSLocatonAlwaysUsageDescription 256 -(void)startDrawLineWithDestinationItem:(MKMapItem *)desItem userItem:(MKMapItem *)userItem{ 257 258 //1.创建一个路线请求 259 MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init]; 260 261 //2.设置起点 262 request.source = userItem; 263 264 //3.设置终点 265 request.destination = desItem; 266 267 //4.创建一个路线管理器 268 MKDirections *direction = [[MKDirections alloc] initWithRequest:request]; 269 270 //5.画线 271 //5.1算路 272 [direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) { 273 274 //5.2遍历请求响应后的路线 275 for (MKRoute *route in response.routes) { 276 277 //5.3拿到画在地图上的线 278 MKPolyline *line = route.polyline; 279 280 //5.4把线添加到地图上 281 [self.mapView addOverlay:line]; 282 } 283 }]; 284 } 285 286 // 渲染线段的代理方法 287 -(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{ 288 289 //创建渲染器 290 MKPolylineRenderer *render = [[MKPolylineRenderer alloc]initWithOverlay:overlay]; 291 292 //设置线段的颜色 293 render.strokeColor = [UIColor redColor]; 294 295 //设置线宽 296 render.lineWidth = 5; 297 298 299 300 return render; 301 302 303 } 304 7.自定义导航提示框 305 已知,当点击大头针的时候,可以显示设置的标题和小标题。 306 这里需求是,点击大头针,在大头针上显示信息框 307 308 点击大头针会触发didSelectAnnotationView 的代理方法 309 在这里添加 信息框,但是信息框不会跟随地图移动,它使相对于屏幕的。 310 所以信息框 也需要用大头针来做 311 312 当点击大头针,触发代理方法时,给mapView添加大头针, 313 这个大头针需要自定义大头针view. 314 添加大头针会触发viewForAnnotation 代理方法,在这个代理方法中 315 创建大头针view 316 317 所以现在的问题是怎样写它的大头针view 318 319 创建类,继承大头针view。在初始化方法中initWithFrame 320 初始化一个uiview,这个uiview返回一个xib(addsubview) 321 322 323 8.百度地图集成 324 1.导入组件 325 导BaiduMapAPI.framework 326 mapapi.bundle // 没导包会-> 引擎加载失败 327 MessageUI.framework 328 OpenGLES.framework 329 QuartzCore.framework 330 CoreLocation.framework 331 SystemConfiguration.framework 332 CoreGraphics.framework 333 Security.framework 334 335 在appdelegate 声明全局的管理类static BMKMapManager * _manager; 336 2.开启百度地图管理 337 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 338 339 _manager = [[BMKMapManager alloc]init]; 340 BOOL ret = [_manager start:@"XWkZFy5el0rx5PzVAVjfDF2k" generalDelegate:self]; 341 342 if (!ret) { 343 NSLog(@"manager start failed"); 344 } 345 346 347 return YES; 348 } 349 350 3.地图集成的状态判断协议方法: 351 - (void)onGetNetworkState:(int)iError{ 352 if (iError != 0) { 353 NSLog(@"网络连接错误"); 354 } 355 } 356 357 /** 358 *返回授权验证错误 359 *@param iError 错误号 : 为0时验证通过,具体参加BMKPermissionCheckResultCode 360 */ 361 - (void)onGetPermissionState:(int)iError{ 362 if (iError != 0) { 363 NSLog(@"授权出错"); 364 } 365 } 366 367 368 组件中有c++程序,需要修改 ViewController.mm 369 4.创建百度地图 370 在创建的百度地图上 添加一个按钮 371 点击按钮 触发查找方法(调用百度POI)point of intersting 372 373 初始化地图,添加按钮 374 - (void)viewDidLoad { 375 [super viewDidLoad]; 376 // 创建百度地图,添加到view 377 BMKMapView * bdView = [[BMKMapView alloc]initWithFrame:self.view.bounds]; 378 379 self.mapView = bdView; 380 381 382 [self.view addSubview:bdView]; 383 384 UIButton * btn = [[UIButton alloc]initWithFrame:CGRectMake(10, 10, 100, 30)]; 385 386 btn.backgroundColor = [UIColor redColor]; 387 [btn addTarget:self action:@selector(searchPOI) forControlEvents:UIControlEventTouchUpInside]; 388 389 [self.view addSubview:btn]; 390 } 391 392 // 按钮点击方法 393 -(void)searchPOI{ 394 395 //创建POI 396 397 398 BMKCitySearchOption *city = [[BMKCitySearchOption alloc]init]; 399 city.city = @"昌平区"; 400 city.keyword = @"电影院"; 401 city.pageIndex = 0; //分页索引,默认0 402 city.pageCapacity = 50; //分页数 403 404 405 BMKPoiSearch *searchRegin = [[BMKPoiSearch alloc]init]; 406 searchRegin.delegate = self; 407 [searchRegin poiSearchInCity:city]; 408 409 410 } 411 5.POI的代理方法 412 // 获得POI结果 413 -(void)onGetPoiResult:(BMKPoiSearch *)searcher result:(BMKPoiResult *)poiResult errorCode:(BMKSearchErrorCode)errorCode{ 414 415 NSLog(@"总结果数:%d",poiResult.totalPoiNum); 416 for (BMKPoiInfo *info in poiResult.poiInfoList) { 417 418 NSLog(@"[ %@ , %@ , %@ , %@ , %@ ]",info.name,info.uid,info.address,info.city,info.phone); 419 420 // 添加大头针 421 BMKPointAnnotation *anno = [[BMKPointAnnotation alloc]init]; 422 anno.coordinate = info.pt; 423 anno.title = info.name; 424 anno.subtitle = info.address; 425 426 [self.mapView addAnnotation:anno]; 427 428 } 429 } 430 431 432 433 // 详细搜索 434 -(void)onGetPoiDetailResult:(BMKPoiSearch *)searcher result:(BMKPoiDetailResult *)poiDetailResult errorCode:(BMKSearchErrorCode)errorCode{ 435 436 NSLog(@".....BMKPoiDetailResult....."); 437 } 438 439 440 6.POI相关的搜索结果类 441 442 /* ??BMKPoiResult 443 ///本次POI搜索的总结果数 444 @property (nonatomic) int totalPoiNum; 445 ///当前页的POI结果数 446 @property (nonatomic) int currPoiNum; 447 ///本次POI搜索的总页数 448 @property (nonatomic) int pageNum; 449 ///当前页的索引 450 @property (nonatomic) int pageIndex; 451 ///POI列表,成员是BMKPoiInfo 452 @property (nonatomic, strong) NSArray* poiInfoList; 453 ///城市列表,成员是BMKCityListInfo 454 @property (nonatomic, strong) NSArray* cityList; 455 */ 456 457 458 /* ??BMKPoiInfo-》poiInfoList 459 ///POI名称 460 @property (nonatomic, strong) NSString* name; 461 ///POIuid 462 @property (nonatomic, strong) NSString* uid; 463 ///POI地址 464 @property (nonatomic, strong) NSString* address; 465 ///POI所在城市 466 @property (nonatomic, strong) NSString* city; 467 ///POI电话号码 468 @property (nonatomic, strong) NSString* phone; 469 ///POI邮编 470 @property (nonatomic, strong) NSString* postcode; 471 ///POI类型,0:普通点 1:公交站 2:公交线路 3:地铁站 4:地铁线路 472 @property (nonatomic) int epoitype; 473 ///POI坐标 474 @property (nonatomic) CLLocationCoordinate2D pt; 475 */ 476 477 478 /* 479 ///POI名称 ??BMKPoiDetailResult 480 @property (nonatomic, strong) NSString* name; 481 ///POI地址 482 @property (nonatomic, strong) NSString* address; 483 ///POI电话号码 484 @property (nonatomic, strong) NSString* phone; 485 ///POIuid 486 @property (nonatomic, strong) NSString* uid; 487 ///POI标签 488 @property (nonatomic, strong) NSString* tag; 489 ///POI详情页url 490 @property (nonatomic, strong) NSString* detailUrl; 491 ///POI所属分类,如“hotel”,“cater”,“life” 492 @property (nonatomic, strong) NSString* type; 493 ///POI地理坐标 494 @property (nonatomic) CLLocationCoordinate2D pt; 495 ///POI价格 496 @property (nonatomic) double price; 497 ///POI综合评分 498 @property (nonatomic) double overallRating; 499 ///POI口味评分 500 @property (nonatomic) double tasteRating; 501 ///POI服务评分 502 @property (nonatomic) double serviceRating; 503 ///POI环境评分 504 @property (nonatomic) double environmentRating; 505 ///POI设施评分 506 @property (nonatomic) double facilityRating; 507 ///POI卫生评分 508 @property (nonatomic) double hygieneRating; 509 ///POI技术评分 510 @property (nonatomic) double technologyRating; 511 ///POI图片数目 512 @property (nonatomic) int imageNum; 513 ///POI团购数目 514 @property (nonatomic) int grouponNum; 515 ///POI评论数目 516 @property (nonatomic) int commentNum; 517 ///POI收藏数目 518 @property (nonatomic) int favoriteNum; 519 ///POI签到数目 520 @property (nonatomic) int checkInNum; 521 ///POI营业时间 522 @property (nonatomic, strong) NSString* shopHours; 523 */ 524 9.原生分享组件(新浪微博分享) 525 需要导入社会分享组件 Social.framework 526 导入头文件#import <Social/Social.h> 527 // 1. 首先需要判断 原生的分享组件 是否支持微博分享 528 529 if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeSinaWeibo]) 530 { 531 // 2.创建分享组件,分享的类型是:新浪微博 532 SLComposeViewController *slview = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeSinaWeibo]; 533 534 // 3.分享的内容 与图片 535 [slview setInitialText:@"分享的内容"]; 536 537 [slview addImage:[UIImage imageNamed:@"图片"]]; 538 539 540 // 4.模态框展示 541 [self presentViewController:slview animated:YES completion:nil]; 542 } 543 544 10.友盟分享-(新浪微博分享组件) 545 10.1通过网页登陆授权 546 547 导入友盟SDK UMSocial_Sdk_4.2.3 548 导入 SystemConfiguration.framework 549 550 a> appdelegate设置 551 导入头文件 #import "UMSocial.h" 552 553 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 554 555 [UMSocialData setAppKey:@"55dece9767e58ea73900083b"]; 556 557 return YES; 558 } 559 b> 触发操作,分享 560 appKey:友盟appID 561 shareText:分享的内容 562 shareImage :分享的图片 563 shareToSnsNames:使用哪些组件分享 564 delegate: 565 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 566 567 [UMSocialSnsService presentSnsController:self appKey:@"55dece9767e58ea73900083b" shareText:@"这里是分享的内容" shareImage:[UIImage imageNamed:@"UMS_comment_tap_white"] shareToSnsNames:@[UMShareToDouban,UMShareToEmail,UMShareToSina,UMShareToSms,UMShareToTwitter] delegate:nil]; 568 569 } 570 571 10.2 通过SSO分享新浪微博 572 使用SSO新浪分享的前提是,必须有安装新浪微博客户端 573 a> appdelegate设置 574 导入 575 #import "UMSocialSinaHandler.h" 576 577 在didFinishLaunchingWithOptions中 578 // SSO 回调地址可以为空,使用此方法,必须处理回调 579 // 还需 配置scheme sina.appkey 580 [UMSocialSinaHandler openSSOWithRedirectURL:nil]; 581 还需要提供回调页的处理方法 582 // 处理回调 583 -(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{ 584 585 return [UMSocialSnsService handleOpenURL:url]; 586 } 587 588 -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ 589 return [UMSocialSnsService handleOpenURL:url]; 590 } 591 b> 分享组件不变化 592 [UMSocialSnsService presentSnsController:self appKey:@"55dece9767e58ea73900083b" shareText:@"这里是分享的内容" shareImage:[UIImage imageNamed:@"UMS_comment_tap_white"] shareToSnsNames:@[UMShareToDouban,UMShareToEmail,UMShareToSina,UMShareToSms,UMShareToTwitter] delegate:nil]; 593 594 595 596 11.地图定位不了,代理方法用不了的解决 597 598 a> 地理定位的授权 599 600 Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first. 601 解决办法: 602 1. 设置授权 603 [self.mgr requestAlwaysAuthorization]; 604 2. 设置info 605 NSLocationAlwaysUsageDescription 606 3. 保持网络连接
原文:http://www.cnblogs.com/lxlmq412/p/4841588.html