關(guān)于iOS 應用如何添加谷歌地圖,網(wǎng)上其實有很多文檔,但當自己實際開發(fā)時,還是會有很多問題,我這次的需求就是地圖國際化,原項目中接的是高德地圖,現(xiàn)在要替換成谷歌地圖,要求功能及頁面的UI顯示要和之前一致(肯定不可能百分百,至少8成像)
一、項目集成Google maps
官方文檔連接
推薦是使用cooapods集成,通常會使用一下兩個sdk
- 'GoogleMaps',基本的定位功能,通常加載這一個sdk就可以了
- 'GooglePlaces',實現(xiàn)搜索功能,官方文檔叫做地點自動完成,可查找周圍的興趣點,即POI
在Podfile添加
pod 'GoogleMaps', '指定版本號'
二、獲取API密匙
前提是已經(jīng)在GoogleMapSDK中創(chuàng)建好自己的應用,需要有自己的Google賬號,我這邊是Android開發(fā)早就申請好了,我復制了APIKey直接使用
三、配置plist文件搭建定位環(huán)境
info.pliste文件中添加定位權(quán)限相關(guān)字段
四、調(diào)用代理方法實現(xiàn)相關(guān)需求
- 在
AppDelegate.m導入框架
#import <GoogleMaps/GoogleMaps.h>
- 在
application:didFinishLaunchingWithOptions方法中添加
[GMSServices provideAPIKey: @"APIKey"];
- 在我們需要顯示地圖的控制器調(diào)用API方法
為了解耦代碼增加可復用性,可以寫一個地圖的類,對地圖做一些簡單的配置,增加一些自定義方法,比如地圖截屏方法,因為項目的需求的是在一個IM空間中,像他人發(fā)送一個地理位置,以聊天氣泡的形式發(fā)送(參考微信中的“發(fā)送位置”)
簡單介紹一下我用到的 GMSMapView的屬性,如果想知道全部的屬性,可以在地圖的sdk加載好之后,點擊進入到 GMSMapView 中查看
- (GMSMapView *)mapView {
if (!_mapView) {
// 根據(jù)經(jīng)緯度和縮放等級,初始化相機,顯示地圖內(nèi)容,用于海外的,最好給個國外的經(jīng)緯度
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:38.8879
longitude:-77.0200
zoom:17];
_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
_mapView.mapType = kGMSTypeNormal;
// 設備當前位置的點和準確性圓圈
_mapView.myLocationEnabled = YES;
// 使用指南針
_mapView.settings.compassButton = YES;
// 當前位置按鈕
_mapView.settings.myLocationButton = YES;
_mapView.settings.indoorPicker = NO;
}
return _mapView;
}
- 需求1:大頭針和當前位置的地址始終顯示在屏幕中間
這時候建議不要使用GMSMarker,因為在實際使用過程中,每當移動地圖,大頭針會一跳一跳的,雖然也是一直顯示在最中間,但是會有間歇性空白,視覺效果不是很好,如果強行用GMSMarker來定義大頭針,操作會很復雜,不如直接定義一個UIImageView,那對應的詳細地址氣泡也需要自定義,最好寫個類,下面還有需求可以復用 - 需求2:地理位置反編譯,本來是要顯示當前位置的POI,但是
GMSMapView沒有一個代理方法可以做到這一點,只有點擊某個興趣點可以拿到那個興趣點的placeID,再根據(jù)placeID做其他操作,但是這不符合需求,需求是任意點都能拿到POI,如果任意點不是POI那就拿到最近的POI信息,這時候只引入GoogleMaps的sdk已經(jīng)不能滿足需求了,需要在 Podfile 中添加 'GooglePlaces'
pod 'GooglePlaces','指定版本號'
但是我實際使用過程中發(fā)現(xiàn),還是不能滿足現(xiàn)在的需求,他的代理方法返回的是附近一些POI點的集合,一個數(shù)組,而且測試發(fā)現(xiàn),這個數(shù)組中的元素,只是你當前設備所在位置周邊的POI的信息,不是隨著你地圖中心位置移動而變化的,達不到想要的效果(也許還有其他方法我沒發(fā)現(xiàn),有經(jīng)驗的大佬請教教我),最后退而求其次,用了 GMSAddress,對當前經(jīng)緯度的位置做了反編譯,做多能拿到當前位置是那條路和郵編。
提示: GMSServices 和 GMSPlacesClient 的 APIKey是不同的,不能使用同一個,
[GMSServices provideAPIKey: @"key1"];
[GMSPlacesClient provideAPIKey: @"key2"];
否則 GooglePlaces 里面類的代理方法使用都會報錯Error Domain=com.google.places.ErrorDomain Code=-3 "An internal error occurred in the Places API library. If you believe this error represents a bug, please file a report using the instructions on our community and support page ([https://developers.google.com/places/ios-sdk/support)](https://developers.google.com/places/ios-sdk/support))." UserInfo={NSLocalizedFailureReason=An internal error occurred in the Places API library. If you believe this error represents a bug, please file a report using the instructions on our community and support page ([https://developers.google.com/places/ios-sdk/support).](https://developers.google.com/places/ios-sdk/support).), NSUnderlyingError=0x171251c10 {Error Domain=com.google.places.api.server.ErrorDomain Code=-2 "This API project is not authorized to use this API." UserInfo={NSLocalizedFailureReason=This API project is not authorized to use this API.}}}
- 需求三3:別人點開我發(fā)送給他的位置,要求地圖可滑動縮放,但是我發(fā)送的位置處會有大頭針及地址氣泡,并且位置固定在對應的經(jīng)緯度,這就和需求1又不一樣了,這時候最方便的就是用sdk中的大頭針
GMSMarker并且自定義大頭針氣泡,在下面這個代理方法中寫視圖
- (nullable UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker;
五、遇到的問題
- 當他人查看我送的位置時,一進入到該頁面要求大頭針氣泡是始終顯示的,這就需要將地圖的
selectedMarker設為當前的大頭針,因為地圖可縮放滑動,當點擊到地圖任意一點,大頭針氣泡都會隱藏,我這邊是在didTapAtCoordinate方法中設置地圖的selectedMarker
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
self.mapView.selectedMarker = self.defaultMarker;
}
- 打開地圖,將地圖中心點移到很遠的地方,大概5分鐘左右,地圖中心點會在自動回到當前設備所在位置,
處理方法:我是將 CLLocationManager 的distanceFilter屬性設置成默認的,感覺是可以的,我自測沒什么問題,具體我也不清楚,等待測試反饋結(jié)果。