iOS开发攻城狮的集散地

iOS开发 - 关于谷歌地图的使用总结

2018-07-23  本文已影响3人  Jackie_123

前段时间遇到项目上需要运用谷歌地图开发,完成之后个人感觉非常的麻烦,主要是相关资料较少,并且谷歌地图的SDK不是特别好啃,并且我相信之后还会有不少人会遇到和我同样的问题,所以今天我在这里做一个比较详细的记录,希望能够帮到有相关需求的人.

  1. 对于iOS开发者,Google地图提供两个开发入口:一个地图的(Maps SDK for iOS),一个是定位的(Places SDK for iOS),你可以去下载google的官方Demo

对于Demo的下载,我的做法是直接打开命令行工具,按照官方文档给的提示,进行操作,下面是我下载定位的Demo

下载定位Demo

他这个Demo的下载方式挺有意思的,下载完成之后如果你想要找到这个程序放的位置,只需要在工程打开后自己找个文件show in finder就行了.(想要查看google的官方文档肯定是需要翻墙的哦) ,下载下来这个Demo之后,如果你想要运行改工程你必须去配置相关服务的key,不然运行会报错,并且如果想要在手机上运行也需要你的手机翻墙才行,这里推荐一个手机的免费的翻墙工具(Screen VPN),免费的,AppStore搜索即可下载,每天有200M免费流量,对于测试完全够了,这个软件的翻墙需要在4G下才行,我用公司的WiFi翻不了.

  1. 你需要根据手里的google的开发者账号,去平台申请第1步说的key,看下图:
创建需要的服务.png
获取凭据.png

首先需要去开放者平台创建服务,然后创建凭据拿到相应的key.在启动了服务并且拿到了key之后,把key填在第1步获取的Demo中的相应的位置就行了.

  1. 简单的介绍一下google地图的基本功能:
    3.1 基本组成部分:

Map(地图): 基本的地图创建, 组件, 类别等;
Panorama(全景): 固定/可旋转的街景;
Overlays(覆盖物): 地图视图的自定义(地图大头针, 弹出信息框等);
Camera(摄像头): 当前地图的可视范围(设置摄像头中心点坐标、镜头缩放比例、方向、视角等);
Services(服务): 地理编码/逆地理编码;

GoogleMap SDK结构概览.png

3.2 常用类介绍:

GMSMapView: 最主要的地图类
GMSCameraPosition: 地图摄像头,可以理解为当前地图的可视范围,可以获取到摄像头中心点坐标、镜头缩放比例、方向、视角等参数
GMSMarker: 地图大头针
GMSGeocoder: 反向地理编码类
GMSAddress: 反向地理编码返回的类,包含坐标及地理位置描述等信息
CLLocationManager: 就是CoreLocation框架下的地理位置管理类
GMSAutocompleteFetcher: 搜索自动补全抓取器,通过该类的代理方法实现搜索自动补全

3.3 常用方法介绍:(GMSMapViewDelegate:)

mapView:willMove: 镜头即将移动时调用
mapView:didChangeCameraPosition: 镜头移动完成后调用
mapView:didTapAtCoordinate: 点击地图时调用
mapView:didLongPressAtCoordinate: 长按地图时调用
mapView:didTapMarker: 点击大头针时调用
mapView:didTapInfoWindowOfMarker: 点击大头针的弹出视窗时调用
mapView:didLongPressInfoWindowOfMarker: 长按大头针视窗时调用
mapView:markerInfoWindow: 自定义大头针弹出视窗,返回UIView
mapView:didCloseInfoWindowOfMarker: 自定义大头针弹出视窗关闭时调用
mapView:didDragMarker: 拖拽大头针时调用
didTapMyLocationButtonForMapView: 点击定位大头针, 返回BOOL值

那么通过上面三点,我相信你应该对google地图有了一个基本的了解,那么下面我再通过代码的方式去看看google地图怎么实现.

我自己的项目中有一个自定义弹窗的需求,google地图有一个比较不友好的问题就是:

如果你需要自定义弹窗是用的SDK提供的代理方法那么在你弹窗的view上面的按钮的点击事件没有作用,解决的办法是自己写一套弹窗的逻辑,通过google,找到了一个第三方叫做SMCalloutView, 在这里也感谢作者的开源,非常棒.

下面是我实现之后的效果展示

自己写弹窗

下面,我贴一下我的代码给大家起一个头:

@property(nonatomic, strong) GMSMapView *mapView;

/** 用户当前所在位置 */

@property(nonatomic, assign) CLLocationCoordinate2D curCoordinate2D;

- (void)createUI{

    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.868

                                                            longitude:151.2086

                                                                 zoom:16];

    GMSMapView*mapView = [GMSMapViewmapWithFrame:CGRectZerocamera:camera];

    mapView.myLocationEnabled = YES;

    [self.viewaddSubview:mapView];

    self.mapView= mapView;

}

- (void)viewDidLayoutSubviews{

    [super viewDidLayoutSubviews];

    self.mapView.frame = self.view.bounds;

}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager*)manager didUpdateLocations:(NSArray*)locations{

    CLLocation*curLocation = [locations lastObject];

    // 通过location  或得到当前位置的经纬度

    CLLocationCoordinate2D curCoordinate2D = curLocation.coordinate;

    GMSCameraPosition*camera = [GMSCameraPosition cameraWithLatitude:curCoordinate2D.latitude longitude:curCoordinate2D.longitude zoom:14];

    self.mapView.camera= camera;

    self.curCoordinate2D= curCoordinate2D;

    if (self.curCoordinate2D.latitude) {

        [self.locationManager stopUpdatingLocation];

    }

}

上面呢,大家就可以拿到当前用户所在的地理位置了,那么接下来我再给大家贴一段关于SMCalloutView是怎么使用的,下面代码中的JNBubbleChange继承的SMCalloutView,用xib拖拽的一个弹出框.

@property (strong, nonatomic) JNBubbleChange *calloutView;

@property(strong, nonatomic) UIView *emptyCalloutView;

- (UIView*)emptyCalloutView

{

   if (!_emptyCalloutView) {

       _emptyCalloutView = [[UIView alloc] init];

       _calloutView.backgroundColor = [UIColor clearColor];

   }

   return _emptyCalloutView;

}

- (JNBubbleChange*)calloutView

{

   if (!_calloutView) {

       _calloutView = [[JNBubbleChange alloc] initWithFrame:CGRectMake(0,0, (JNScreenW-JNW(60)),JNH(160))];

   }

   return _calloutView;

}

#pragma mark - GMSMapViewDelegate

- (nullableUIView*)mapView:(GMSMapView*)mapView markerInfoWindow:(GMSMarker*)marker{

   CLLocationCoordinate2D anchor = marker.position;

   CGPoint point = [mapView.projection pointForCoordinate:anchor];

   self.calloutView.calloutOffset = CGPointMake(0, -CalloutYOffset);

   self.calloutView.hidden = NO;

   CGRectcalloutRect = CGRectZero;

   calloutRect.origin = point;

   calloutRect.size = CGSizeZero;

   //确定一个对象是否是当前类的成员

   if([marker isMemberOfClass:[JNCusGmsMaker class]]){

       JNCusGmsMaker *jMarker = (JNCusGmsMaker*) marker;

       self.calloutView.dict = jMarker.shopDict;

       self.calloutView.daoB.dict = jMarker.shopDict;

       self.calloutView.detailB.dict = jMarker.shopDict;

   }

   [self.calloutView.daoB addTarget:self action:@selector(clickDaoB:) forControlEvents:UIControlEventTouchUpInside];

   [self.calloutView.detailB addTarget:self action:@selector(clickDetailB:) forControlEvents:UIControlEventTouchUpInside];

   [self.calloutView presentCalloutFromRect:calloutRect inView:mapView constrainedToView:mapView animated:YES];

   return self.emptyCalloutView;

}

上面的这一段代码就是点击标注的时候弹窗的显示框,其中的JNCusGmsMaker是继承的GMSMarker,里面加了一个字典属性,目的很简单就是让对应的maker去相应的保存服务器中获取的值,最后返回一个空的UIView给系统即可.

  1. 再给大家贴一下关于如何用google地图导航到相应的地点
    首先,google提供的SDK中没有关于导航的,那么我的做法是拿到目的地的坐标后跳转到googleMap的客户端去导航,方法如下:
#pragma mark - 标注按钮点击事件

-(void)clickDaoB:(JNBaseVarBtn*)sender{

    if(!kDictIsEmpty(sender.dict)){

        NSURL *url = JNUrl(@"comgooglemaps://");

        if ([[UIApplication sharedApplication] canOpenURL:url]) {

            CGFloat lati = [sender.dict[@"latitude" ] floatValue];

            CGFloat loti = [sender.dict[@"longitude"] floatValue];;

            NSString *desS = [NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving",@"你的App名称",JNAppScheme,lati,loti];

            NSString *urlString = [desS stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];

        }else{

            [M showAlert:@"请先安装谷歌地图客户端"];

        }

    }

}

5.关于google地图的反地理位置编码
对于google地图的反地理位置编码,我的做法是在拿到用户的经纬度时,去根据经纬度拿到其位置,再给大家贴一小段代码

//反地理编码

-(void)reversiGeocode:(CLLocationCoordinate2D)target{

    [JNHudTool mb_showHUDWithInfo:nil userEnaled:YES someView:self.JNBaseTableview];

    [self.searchAddressArrayM removeAllObjects];

    [[GMSGeocoder geocoder] reverseGeocodeCoordinate:target completionHandler:^(GMSReverseGeocodeResponse * response, NSError * error) {

        if(response.results) {

            for(inti =0; i < response.results.count; i ++ ) {

                GMSAddress*temp = response.results[i];

                if(!kStringIsEmpty(temp.thoroughfare)) {

                    [self.searchAddressArrayMaddObject:temp];

                }

            }

            NSLog(@"查看反地理编码的结果res:%@",response.results);

            [self.JNBaseTableviewreloadData];

            [JNHudTool mb_dismissHUDWithTime:2 someView:self.JNBaseTableview];

        }

    }];

}

其他的关于输入某个地点进行搜索的话,可以直接用google提供的一个控制器,叫做(GMSAutocompleteViewController),这个大家可以自己去下第1步中的Demo简单看下就可以了

以上就是我最近遇到的关于google地图的问题和解决方法,希望对之后也遇到此问题的朋友有一些帮助.下面的链接是我在解决的过程中用到的资料,也是非常的感谢作者:

https://juejin.im/post/59de263551882578bf1847b9

上一篇下一篇

猜你喜欢

热点阅读