最近由于公司项目做的是国外的项目,使用到了GoogleMaps SDK ,期间磕磕碰碰各种查资料看官方文档总算完成了地图方面的功能,现在和大家分享一下Google地图功能的实现,自己也记录下以后用到可以在看看,同时祝大家项目顺利。
很感谢其他作者的分享,少走了点弯路。
集成步骤及GoogleMaps的常用方法地址
GoogleMaps SDK for iOS 详细集成地址: www.jianshu.com/p/dc7d267d63d0
GoogleMaps 常用方法介绍: www.jianshu.com/p/ec6d154e3928
iOS--谷歌地图相关功能的实现 : www.jianshu.com/p/2a1bf192e496
以上3个链接附有GoogleMaps的集成方式以及代理方法详细介绍。
获取定位信息
首先要通过CLLocation拿到定位信息,并且用户授权访问位置信息等,这里不详细介绍,直接上代码。
//获取现在的定位位置
- (void)getNowLocation{
if ([CLLocationManager locationServicesEnabled]){//判断是否打开定位
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager requestWhenInUseAuthorization];//请求前台定位权限
[self.locationManager requestAlwaysAuthorization];//请求后台定位权限
[self.locationManager setDistanceFilter:10];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager startUpdatingLocation];
}else{
//不能定位用户的位置
//1.提醒用户检查当前的网络状况
//2.提醒用户打开定位开关
[MBProgressHUD showError:@"Switch on the position switch,please"];
}
}
初始化地图等信息
- (void)creatGoogleMaps{
//初始化google地图
_polyline = [[GMSPolyline alloc] init];
_linepath = [GMSMutablePath path];
_lastMark = [[GMSMarker alloc] init];
self.mapView = [[GMSMapView alloc] initWithFrame:CGRectZero];
self.mapView.indoorEnabled = NO;
//根据自己需要设置地图缩放最大最小比例
[self.mapView setMinZoom:3 maxZoom:19];
self.mapView.buildingsEnabled = NO;
self.mapView.settings.rotateGestures = NO;
self.mapView.settings.tiltGestures = NO;
self.mapView.myLocationEnabled = YES;
self.mapView.delegate = self;
[self.view addSubview:self.mapView];
[self.mapView makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
//地图中心标记
[self createCenterViw];
//初始化弹出框
self.homeMenuView = [HomeMenuView instanceView];
self.cyclingMenuView = [CyclingNowView instanceView];
}
简单的地图中心标记
//中间定位图标显示
- (void)createCenterViw{
UIImageView *centerImageView=[[UIImageView alloc]init];
[centerImageView setImage:[UIImage imageNamed:@"ziji"]];
[self.view addSubview:centerImageView];
[centerImageView makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.view);
make.centerY.equalTo(self.view).offset(-20.5);
}];
}
定位代理方法实现
因为googlemaps在国内定位坐标不准确,期间也做了国内和国外火星坐标的处理,后面因为好像不在国内使用,就注释了,方便以后可能会用。
#pragma mark - CLLocationManagerDelegate
//拿到授权发起定位请求
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self.locationManager startUpdatingLocation];
NSLog(@"locationmanager ===== %f",self.locationManager.location.coordinate.longitude);
}
}
//位置更新时调用
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray*)locations{
// 通过location 或得到当前位置的经纬度
CLLocation *currentLocation = locations.firstObject;
CLLocationCoordinate2D curCoordinate2D=currentLocation.coordinate;
[[NSUserDefaults standardUserDefaults] setDouble:curCoordinate2D.latitude forKey:@"latitude"];
[[NSUserDefaults standardUserDefaults] setDouble:curCoordinate2D.longitude forKey:@"longitude"];
self.mapView.camera = [[GMSCameraPosition alloc] initWithTarget:curCoordinate2D zoom:17 bearing:0 viewingAngle:0];
self.marker.position = CLLocationCoordinate2DMake(curCoordinate2D.latitude, curCoordinate2D.longitude);
/* 中国火星坐标判断
BOOL ischina = [[ZCChinaLocation shared] isInsideChina:(CLLocationCoordinate2D){curCoordinate2D.latitude,curCoordinate2D.longitude}];
if (!ischina) {
[[NSUserDefaults standardUserDefaults] setDouble:curCoordinate2D.latitude forKey:@"latitude"];
[[NSUserDefaults standardUserDefaults] setDouble:curCoordinate2D.longitude forKey:@"longitude"];
self.mapView.camera = [[GMSCameraPosition alloc] initWithTarget:curCoordinate2D zoom:17 bearing:0 viewingAngle:0];
self.marker.position = CLLocationCoordinate2DMake(curCoordinate2D.latitude, curCoordinate2D.longitude);
}
else{
CLLocationCoordinate2D curCoordinate = [TQLocationConverter transformFromWGSToGCJ:curCoordinate2D];
[[NSUserDefaults standardUserDefaults] setDouble:curCoordinate.latitude forKey:@"latitude"];
[[NSUserDefaults standardUserDefaults] setDouble:curCoordinate.longitude forKey:@"longitude"];
self.mapView.camera = [[GMSCameraPosition alloc] initWithTarget:curCoordinate zoom:17 bearing:0 viewingAngle:0];
self.marker.position = CLLocationCoordinate2DMake(curCoordinate.latitude, curCoordinate.longitude);
}
*/
double latitude = [[NSUserDefaults standardUserDefaults]doubleForKey:@"latitude"];
double longitude = [[NSUserDefaults standardUserDefaults]doubleForKey:@"longitude"];
NSLog(@"我拿到经度了==%f 我拿到纬度了==%f",longitude,latitude);
//像服务端发送获取当前位置周边车辆请求
[self getBikeAndBaseStationInfoWithLocationLongitude:longitude andLatitude:latitude];
//取最新的一个定位值
self.newloc = [[locations lastObject] coordinate];
[self.locationManager stopUpdatingLocation];
}
google地图代理方法实现
//镜头移动完成后调用
- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position{
//反向地理编码
// [self getBikeAndBaseStationInfoWithLocationLongitude:position.target.longitude andLatitude:position.target.latitude];
[[GMSGeocoder geocoder]reverseGeocodeCoordinate:position.target completionHandler:^(GMSReverseGeocodeResponse * response, NSError * error) {
if (response.results) {
GMSAddress *address = response.results[0];
NSLog(@"%@",address.thoroughfare);
}
}];
}
//点击大头针的弹出视窗时调用
-(void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker{
NSLog(@"点击大头针的弹出视窗时调用");
}
//拖拽大头针时调用
-(void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker{
NSLog(@"拖拽大头针时调用");
}
//大头针拖拽完成时调用
-(void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker{
NSLog(@"大头针拖拽完成时调用");
}
//点击大头针时调用
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker{
NSLog(@"点击大头针... mark.userData:%@",marker.userData);
//给点击的mark赋值,方便加入坐标数组
self.lastMark = marker;
//获取路径点数组
SMBikeInfoModel *model = marker.userData;
[self showMenuView];
[self showStationDetailMenuView:model];
[self calculateRoutesFrom:self.newloc to:marker.position];
return YES;
}
*计算轨迹线路径、行驶距离及时间
#pragma mark - 画轨迹线
//注:需要画轨迹线,所以必须向googlemap官网请求api,获取到路径规划的数组点
//计算路线 由开始到结束路线请求
- (void)calculateRoutesFrom:(CLLocationCoordinate2D)startLoc to:(CLLocationCoordinate2D)endLoc{
//开始地址
NSString *startAddress = [NSString stringWithFormat:@"%f,%f",startLoc.latitude,startLoc.longitude];
//结束地址
NSString *endAddress = [NSString stringWithFormat:@"%f,%f",endLoc.latitude,endLoc.longitude];
SMNetworking *network = [SMNetworking sharedTool];
NSString *urlString = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@&mode=walking&key=%@",startAddress,endAddress,GoogleDirectionsKey];
[network GET:urlString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *dict = (NSDictionary *)responseObject;
NSArray *routesarray = dict[@"routes"];
NSLog(@"%@",routesarray);
//无路线方案、防崩溃
if (routesarray.count==0) {
[MBProgressHUD showError:@"NO Routes"];
return ;
}
NSDictionary *legsDic = [routesarray objectAtIndex:0];
NSArray *legsArray = [NSArray array];
legsArray = legsDic[@"legs"];
NSDictionary *addressDic = [legsArray objectAtIndex:0];
//起点终点
NSString *startAddressStr = addressDic[@"start_address"];
NSString *endAddressStr = addressDic[@"end_address"];
NSLog(@"起点:%@ 终点:%@",startAddressStr,endAddressStr);
//距离
NSDictionary *distanceDic = addressDic[@"distance"];
NSString *distanceStr = distanceDic[@"text"];
//花费时间
NSDictionary *durationDic = addressDic[@"duration"];
NSString *durationStr = durationDic[@"text"];
NSString *dis = [distanceStr stringByReplacingOccurrencesOfString:@"" withString:@"km"];
NSString *minStr = [durationStr stringByReplacingOccurrencesOfString:@"" withString:@"min"];
NSString *hoursStr = [minStr stringByReplacingOccurrencesOfString:@"小时" withString:@"hour"];
self.homeMenuView.distance.text = dis;
self.homeMenuView.time.text = minStr;
NSDictionary *tempDic = legsDic[@"overview_polyline"];
NSString *points = tempDic[@"points"];
self.routesArray = [self decodePolyLine:[points mutableCopy]];
NSLog(@"points:%@",points);
//画轨迹线
[self showMenuView];
[self.linepath removeAllCoordinates];//移除以前的路径轨迹
[self update_rpute_view];//画线
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
// [MBProgressHUD showError:@"路线请求超时"];
}];
}
*画线
- (void)update_rpute_view{
//线条颜色
self.polyline.strokeColor = SETCOLOR(71, 215, 205);
//线条宽度
self.polyline.strokeWidth = 6.0f;
for (int i = 0; i < self.routesArray.count; i++) {
CLLocation *location = [self.routesArray objectAtIndex:i];
CLLocationDegrees latitude = location.coordinate.latitude;
CLLocationDegrees longitude = location.coordinate.longitude;
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
[self.linepath addCoordinate:coordinate];
}
self.polyline.path = self.linepath;
self.polyline.map = self.mapView;
NSLog(@"count:%lu --- path:%@",(unsigned long)self.polyline.path.count,self.polyline.path.encodedPath);
//展示当前路线
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithPath:self.linepath];
GMSCameraUpdate *update = [GMSCameraUpdate fitBounds:bounds];
[self.mapView moveCamera:update];
}
*得到路径数组
- (NSMutableArray *)decodePolyLine:(NSMutableString *)encoded{
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [NSMutableArray array];
NSInteger lat = 0;
NSInteger lng = 0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[NSNumber alloc]initWithFloat:lat * 1e-5 ];
NSNumber *lontitude = [[NSNumber alloc]initWithFloat:lng * 1e-5];
printf("[%f",[latitude doubleValue]);
printf(" %f]",[lontitude doubleValue]);
CLLocation *loction = [[CLLocation alloc]initWithLatitude:[latitude floatValue] longitude:[lontitude floatValue]];
[array addObject:loction];
}
//加上最后一组轨迹(即加入一组为点击的mark坐标)
CLLocation *lastLoc = [[CLLocation alloc]initWithLatitude:self.lastMark.position.latitude longitude:self.lastMark.position.longitude];
[array addObject:lastLoc];
return array;
}