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. 保持网络连接