iOS Google地圖開發(fā)小結(jié)(2017)

最近接觸了一個(gè)international的項(xiàng)目, 用到Google地圖, 在此稍微總結(jié)一下, 方便以后使用;

一. 準(zhǔn)備工作

相關(guān)資料:
Google地圖API
官方Google地圖API

SMCalloutView
這個(gè)是點(diǎn)擊大頭針彈出信息框的自定義視圖, 官方地圖自定義有局限性, 下面??會(huì)講到, 示例如圖:

自定義視圖

二.開發(fā)內(nèi)容

對(duì)于iOS開發(fā)者, Google地圖提供了兩個(gè)開發(fā)入口:
Maps SDK for iOS
添加 Google 地圖

Places API for iOS
添加位置的最新信息

1.Places API for iOS

這個(gè)一般開發(fā)Google地圖用不到, 不過還是簡單說一下, 官方demo截圖;

Places API官方demo截圖

section0: (Autocomplete)


Autocomplete

Autocomplete主要功能是搜索相關(guān)的位置信息(文本方式);
里面還會(huì)展示UISearchBar/UISearchViewController的幾種呈現(xiàn)方法, 感興趣的可以看看;

section1: (Programmatic APIs)

Programmatic APIs

Programmatic APIs主要展示搜索或所選點(diǎn)附近的信息(地圖方式);

2.Maps SDK for iOS

重點(diǎn)介紹內(nèi)容, mark, mark....
還是一樣, 先看下官方demo, 大概瀏覽一下Google地圖的功能;

//基本組成部分
Map(地圖): 基本的地圖創(chuàng)建, 組件, 類別等;
Panorama(全景): 固定/可旋轉(zhuǎn)的街景;
Overlays(覆蓋物): 地圖視圖的自定義(地圖大頭針, 彈出信息框等);
Camera(攝像頭): 當(dāng)前地圖的可視范圍(設(shè)置攝像頭中心點(diǎn)坐標(biāo)断凶、鏡頭縮放比例、方向巫俺、視角等);
Services(服務(wù)): 地理編碼/逆地理編碼;

結(jié)構(gòu)概覽:


Maps SDK Demos 結(jié)構(gòu)概覽
2.1 常用類介紹:
GMSMapView 最主要的地圖類
GMSCameraPosition 地圖攝像頭认烁,可以理解為當(dāng)前地圖的可視范圍,可以獲取到攝像頭中心點(diǎn)坐標(biāo)介汹、鏡頭縮放比例却嗡、方向、視角等參數(shù)
GMSMarker 地圖大頭針
GMSGeocoder 反向地理編碼類
GMSAddress 反向地理編碼返回的類,包含坐標(biāo)及地理位置描述等信息
CLLocationManager 就是CoreLocation框架下的地理位置管理類
GMSAutocompleteFetcher 搜索自動(dòng)補(bǔ)全抓取器嘹承,通過該類的代理方法實(shí)現(xiàn)搜索自動(dòng)補(bǔ)全
2.2 常用方法介紹:

GMSMapViewDelegate:

mapView:willMove: 鏡頭即將移動(dòng)時(shí)調(diào)用
mapView:didChangeCameraPosition:鏡頭移動(dòng)完成后調(diào)用mapView:didTapAtCoordinate: 點(diǎn)擊地圖時(shí)調(diào)用
mapView:didLongPressAtCoordinate: 長按地圖時(shí)調(diào)用
mapView:didTapMarker: 點(diǎn)擊大頭針時(shí)調(diào)用
mapView:didTapInfoWindowOfMarker: 點(diǎn)擊大頭針的彈出視窗時(shí)調(diào)用
mapView:didLongPressInfoWindowOfMarker: 長按大頭針視窗時(shí)調(diào)用
mapView:markerInfoWindow: 自定義大頭針彈出視窗窗价,返回UIView
mapView:didCloseInfoWindowOfMarker: 自定義大頭針彈出視窗關(guān)閉時(shí)調(diào)用
mapView:didDragMarker: 拖拽大頭針時(shí)調(diào)用
didTapMyLocationButtonForMapView: 點(diǎn)擊定位大頭針, 返回BOOL值
2.3 Google Maps URL 架構(gòu)(單獨(dú)介紹一下):

確實(shí)與國內(nèi)不同, Google地圖URL架構(gòu)沒在demo中提及;
??介紹一下:


iOS 版 Google Maps 應(yīng)用支持以下 URL 架構(gòu):

  • comgooglemaps://
    comgooglemaps-x-callback://
    – 這些架構(gòu)允許您啟動(dòng) iOS 版 Google Maps 應(yīng)用,并執(zhí)行下列幾項(xiàng)操作之一:
    • 以指定的縮放級(jí)別顯示指定位置的地圖叹卷。
    • 搜索位置或地點(diǎn)撼港,并將它們顯示在地圖上。
    • 請(qǐng)求從一個(gè)位置前往另一個(gè)位置的路線骤竹。 可以返回以下四種交通方式的路線:駕車帝牡、步行、騎自行車和乘坐公共交通工具蒙揣。
    • 向應(yīng)用添加導(dǎo)航靶溜。
    • 當(dāng)應(yīng)用完成后,使用 comgooglemaps-x-callback://
      發(fā)出一個(gè)回調(diào)懒震。 回調(diào)經(jīng)常用來使用戶返回到最初打開 iOS 版 Google Maps 的應(yīng)用墨技。
  • comgooglemapsurl:// – 此架構(gòu)允許您使用從桌面 Google Maps 網(wǎng)站得到的 URL 啟動(dòng) iOS 版 Google Maps 應(yīng)用。 這意味著您可以為用戶提供原生移動(dòng)體驗(yàn)挎狸,而不是簡單地加載 Google Maps 網(wǎng)站。
    • 原始 URL 可以是 maps.google.com断楷,或者 google.com/maps锨匆,也可以使用任何有效的國家代碼頂級(jí)域名來代替 com。
    • 您還可以傳遞 goo.gl/maps 重定向 URL冬筒。
      您可以將 x-source 和 x-success 參數(shù)與 comgooglemapsurl:// URL 架構(gòu)結(jié)合使用來發(fā)出回調(diào)恐锣。

2.3.1 檢查設(shè)備上是否已安裝 Google Maps 應(yīng)用;

if ([[UIApplication sharedApplication] canOpenURL:
     [NSURL URLWithString:@"comgooglemaps://"]]) {
      //已安裝Google地圖APP
} else {
     //未安裝Google地圖APP
}

2.3.2 顯示地圖
參數(shù):

  • center:這是地圖視口中心點(diǎn)。 其格式為用逗號(hào)分隔的字符串 latitude,longitude舞痰。
  • mapmode:設(shè)置所顯示地圖的種類土榴。 可以設(shè)置為:standard 或 streetview。 如果未指定响牛,則將使用當(dāng)前的應(yīng)用設(shè)置玷禽。
  • views:開啟/關(guān)閉特定視圖赫段。 可以設(shè)置為:satellitetraffictransit矢赁。 可以使用逗號(hào)分隔符來設(shè)置多個(gè)值糯笙。 如果指定了不帶任何值的參數(shù),那么將清除所有的視圖撩银。
  • zoom:指定地圖的縮放級(jí)別给涕。
//示例 URL,它以紐約為中心额获、采用 14 級(jí)縮放級(jí)別來顯示地圖够庙,且開啟了交通視圖
comgooglemaps://?center=40.765819,-73.975866&zoom=14&views=traffic

2.3.3 搜索
參數(shù):

  • q:用于搜索的查詢字符串。
//示例 URL 用來在指定位置附近搜索“Pizza"
comgooglemaps://?q=Pizza&center=37.759748,-122.427135

2.3.4 顯示路線
參數(shù):

  • saddr:設(shè)置路線搜索的起點(diǎn)抄邀。 它可以是一個(gè)緯度耘眨、經(jīng)度或查詢格式的地址。 如果它是返回多個(gè)結(jié)果的查詢字符串撤摸, 將選擇第一個(gè)結(jié)果毅桃。 如果該值留空,那么將使用該用戶的當(dāng)前位置准夷。
  • daddr:設(shè)置路線搜索的終點(diǎn)钥飞。 具有與 saddr 相同的格式和行為。
  • directionsmode:交通方式衫嵌。 可以設(shè)置為:driving读宙、transitbicyclingwalking楔绞。
// 示例 URL 用來顯示 Google 紐約辦事處與肯尼迪國際機(jī)場之間的交通路線
comgooglemaps://?saddr=Google+Inc,+8th+Avenue,+New+York,+NY&daddr=John+F.+Kennedy+International+Airport,+Van+Wyck+Expressway,+Jamaica,+New+York&directionsmode=transit

2.3.5 指定回調(diào)URL
參數(shù):

  • x-source – 發(fā)送 x-callback 請(qǐng)求的應(yīng)用的名稱结闸。 最好使用短名稱。
  • x-success – 完成時(shí)調(diào)用的 URL酒朵。 通常桦锄,這是您自己的應(yīng)用的 URL 架構(gòu),可以讓用戶返回到原來的應(yīng)用蔫耽。
// 示例將啟動(dòng) iOS 版 Google Maps 應(yīng)用结耀,并以紐約為中心顯示地圖。 該應(yīng)用還會(huì)顯示標(biāo)有“SourceApp”的按鈕匙铡。 當(dāng)點(diǎn)擊“SourceApp”按鈕時(shí)图甜,iOS 版 Google Maps 應(yīng)用將發(fā)出一個(gè)指向虛擬的 URL 架構(gòu)的回調(diào), sourceapp://?resume=true.
comgooglemaps-x-callback://?center=40.765819,-73.975866&zoom=14
  &x-success=sourceapp://?resume=true
  &x-source=SourceApp

2.3.6 向應(yīng)用添加導(dǎo)航

// 代碼展示了如何使用 comgooglemaps-x-callback:// 架構(gòu)來請(qǐng)求路線鳖眼,然后在您的用戶準(zhǔn)備就緒后返回到您的應(yīng)用黑毅。 該代碼將執(zhí)行以下操作
NSURL *testURL = [NSURL URLWithString:@"comgooglemaps-x-callback://"];
if ([[UIApplication sharedApplication] canOpenURL:testURL]) {
  NSString *directionsRequest = @"comgooglemaps-x-callback://" +
      @"?daddr=John+F.+Kennedy+International+Airport,+Van+Wyck+Expressway,+Jamaica,+New+York" +
      @"&x-success=sourceapp://?resume=true&x-source=AirApp";
  NSURL *directionsURL = [NSURL URLWithString:directionsRequest];
  [[UIApplication sharedApplication] openURL:directionsURL];
} else {
  NSLog(@"Can't use comgooglemaps-x-callback:// on this device.");
}

該代碼將執(zhí)行以下操作:

  • 驗(yàn)證 comgooglemaps-x-callback:// URL 架構(gòu)是否可用。
  • 啟動(dòng) iOS 版 Google Maps 應(yīng)用钦讳,并請(qǐng)求前往紐約市肯尼迪國際機(jī)場的路線矿瘦。 將起始地址留空即可請(qǐng)求從用戶的當(dāng)前位置出發(fā)的路線枕面。
  • 將標(biāo)記為“AirApp”的按鈕添加到 iOS 版 Google Maps 應(yīng)用中。 該按鈕標(biāo)簽由 x-source 參數(shù)定義匪凡。
  • 當(dāng)用戶點(diǎn)擊返回按鈕時(shí)膊畴,調(diào)用虛擬 URL 架構(gòu) sourceapp://,。

三.遇到的問題

開發(fā)中難免遇到一些稀奇古怪的問題, 這里就著我遇到的問題分享一下;

需求:
實(shí)現(xiàn)一個(gè)自定義的彈窗, 要求點(diǎn)擊彈窗左邊視圖返回上一頁, 點(diǎn)擊右邊視圖跳轉(zhuǎn)導(dǎo)航功能;

問題:
mapView:markerInfoWindow:中我自定義了一個(gè)氣泡視圖, 視圖左右各一個(gè)按鈕, 按鈕的點(diǎn)擊方法被屏蔽, 只響應(yīng)了整個(gè)氣泡視圖的點(diǎn)擊方法(mapView:didTapInfoWindowOfMarker:);

解決辦法:
在試了n個(gè)方法后, 終于讓我找到了SMCalloutView, github上的一個(gè)自定義氣泡的三方, 可以自由定義左右,中間, 背景視圖, 非常棒??, O(∩_∩)O哈哈~

首先是基礎(chǔ)操作:

#import <SMCalloutView/SMCalloutView.h>

static const CGFloat CalloutYOffset = 10.0f;

@interface ViewController ()
@property (strong, nonatomic) SMCalloutView *calloutView;
@property (strong, nonatomic) UIView *emptyCalloutView;
@end

之后初始化SMCalloutView, 創(chuàng)建一個(gè)空View;

- (void)viewDidLoad
{
        self.calloutView = [[SMCalloutView alloc] init];
    self.calloutView.contentView = [UIView new];
    
    self.emptyCalloutView = [[UIView alloc] initWithFrame:CGRectZero];
}

其次是GMSMapViewDelegate里面的設(shè)置:

- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
    CLLocationCoordinate2D anchor = marker.position;
    
    CGPoint point = [mapView.projection pointForCoordinate:anchor];
    
    self.calloutView.calloutOffset = CGPointMake(0, -CalloutYOffset);
    
    //SMCalloutView中contentView
    UIView *googleTipView = [UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 50);
    
    //左方按鈕
    UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
    [googleTipView addSubview:bView];
    [leftButton addTarget:self action:@selector(leftButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    
    //右方按鈕
    UIButton *rightButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 0, 100, 50)];
    [googleTipView addSubview:bView];
    [rightButton addTarget:self action:@selector(rightButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    
    //取消默認(rèn)背景
    SMCalloutBackgroundView *calloutBgView = [[SMCalloutBackgroundView alloc] initWithFrame:CGRectZero];
    
    self.calloutView.backgroundView = calloutBgView;
    self.calloutView.contentView = googleTipView;
    
    self.calloutView.hidden = NO;
    
    CGRect calloutRect = CGRectZero;
    calloutRect.origin = point;
    calloutRect.size = CGSizeZero;
    
    [self.calloutView presentCalloutFromRect:calloutRect
                                      inView:mapView
                           constrainedToView:mapView
                                    animated:YES];
    
    return self.emptyCalloutView;
}

- (void)mapView:(GMSMapView *)pMapView didChangeCameraPosition:(GMSCameraPosition *)position {
    if (pMapView.selectedMarker != nil && !self.calloutView.hidden) {
        CLLocationCoordinate2D anchor = [pMapView.selectedMarker position];

        CGPoint arrowPt = self.calloutView.backgroundView.arrowPoint;
        CGPoint pt = [pMapView.projection pointForCoordinate:anchor];
        pt.x -= arrowPt.x;
        pt.y -= arrowPt.y + CalloutYOffset;

        self.calloutView.frame = (CGRect) {.origin = pt, .size = self.calloutView.frame.size };
    } else {
        self.calloutView.hidden = YES;
    }
}

- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
    self.calloutView.hidden = YES;
}

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
    mapView.selectedMarker = marker;
    return YES;
}

結(jié)果就可以在點(diǎn)擊方法里面盡情的調(diào)用了:

//左邊按鈕點(diǎn)擊方法
- (void)leftButtonClick:(UIButton *)button{
    
}
//右邊按鈕點(diǎn)擊方法
- (void)rightButtonClick:(UIButton *)button{
    
}

最后感謝這位網(wǎng)友的分享, 附上鏈接:
stackoverflow網(wǎng)友的分享

關(guān)于Google地圖開發(fā):
iOS Google地圖SDK入門教程
iOS--谷歌地圖相關(guān)功能的實(shí)現(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末病游,一起剝皮案震驚了整個(gè)濱河市唇跨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衬衬,老刑警劉巖买猖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異滋尉,居然都是意外死亡玉控,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門狮惜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來高诺,“玉大人,你說我怎么就攤上這事碾篡∈” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵开泽,是天一觀的道長牡拇。 經(jīng)常有香客問我,道長穆律,這世上最難降的妖魔是什么惠呼? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮峦耘,結(jié)果婚禮上剔蹋,老公的妹妹穿的比我還像新娘。我一直安慰自己辅髓,他們只是感情好泣崩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著利朵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猎莲。 梳的紋絲不亂的頭發(fā)上绍弟,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音著洼,去河邊找鬼樟遣。 笑死而叼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的豹悬。 我是一名探鬼主播葵陵,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼瞻佛!你這毒婦竟也來了脱篙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤伤柄,失蹤者是張志新(化名)和其女友劉穎绊困,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體适刀,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秤朗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了笔喉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片取视。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖常挚,靈堂內(nèi)的尸體忽然破棺而出作谭,到底是詐尸還是另有隱情,我是刑警寧澤待侵,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布丢早,位于F島的核電站,受9級(jí)特大地震影響秧倾,放射性物質(zhì)發(fā)生泄漏怨酝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一那先、第九天 我趴在偏房一處隱蔽的房頂上張望农猬。 院中可真熱鬧,春花似錦售淡、人聲如沸斤葱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揍堕。三九已至,卻和暖如春汤纸,著一層夾襖步出監(jiān)牢的瞬間衩茸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工贮泞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留楞慈,地道東北人幔烛。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像囊蓝,于是被迫代替她去往敵國和親饿悬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容