前段时间遇到项目上需要运用谷歌地图开发,完成之后个人感觉非常的麻烦,主要是相关资料较少,并且谷歌地图的SDK不是特别好啃,并且我相信之后还会有不少人会遇到和我同样的问题,所以今天我在这里做一个比较详细的记录,希望能够帮到有相关需求的人.
- 对于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翻不了.
- 你需要根据手里的google的开发者账号,去平台申请第1步说的key,看下图:
获取凭据.png
首先需要去开放者平台创建服务,然后创建凭据拿到相应的key.在启动了服务并且拿到了key之后,把key填在第1步获取的Demo中的相应的位置就行了.
- 简单的介绍一下google地图的基本功能:
3.1 基本组成部分:
GoogleMap SDK结构概览.pngMap(地图): 基本的地图创建, 组件, 类别等;
Panorama(全景): 固定/可旋转的街景;
Overlays(覆盖物): 地图视图的自定义(地图大头针, 弹出信息框等);
Camera(摄像头): 当前地图的可视范围(设置摄像头中心点坐标、镜头缩放比例、方向、视角等);
Services(服务): 地理编码/逆地理编码;
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给系统即可.
- 再给大家贴一下关于如何用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地图的问题和解决方法,希望对之后也遇到此问题的朋友有一些帮助.下面的链接是我在解决的过程中用到的资料,也是非常的感谢作者:
网友评论