入门
留意:
- MapViewController.swift:这是这个项意图主视图控制器,在本教程中你只会运用这个控制器。
- GoogleDataProvider.swift:这是一个用于进行 Google API 调用的包装类。您将在本教程的后面部分查看它包括的办法。
- GooglePlace.swift:这是从 Google 回来的地址成果的模型。
-
MarkerInfoView.swift:这是
UIView
显现地址详细信息的子类。它带有一个匹配的 xib 文件。
在开端编码之前,最好先了解一下应用程序是怎样工作的。构建并运转您的应用程序;您将看到以下屏幕呈现:
现在你会看到一个空白屏幕,中间有一个大头针。按导航栏右侧的操作按钮能够看到如下TypesTableViewController
屏幕:
这就是现在在应用程序中看到的全部内容 – 由您来增加一些魔法!
创立 API 密钥
您首要需求的是一些用于 Google Maps SDK 的 API 密钥以及您将运用的 Google API。假如您还没有 Google 帐户,请创立一个(它们是免费的!)并登录到Google Developers Console。
单击Create Project,将您的项目命名为Feed Me,然后单击Create:
假如您的项目没有立即呈现,请改写页面直到呈现。挑选新创立的项目以拜访其设置。从左边窗格菜单中挑选APIs & SERVICES,然后挑选Library :
查找并启用这些 API:
- 适用于 iOS 的 Google 地图 SDK
- Google Places API 网络服务
在左边窗格菜单中的API 和服务下挑选凭据。单击Create credentials,然后单击API key创立密钥:
仿制密钥并单击封闭:
稍后您将运用该密钥,但首要您将增加实际的 Google Maps iOS SDK。
增加 SDK
翻开Podfile(在Pods项目中)并在上面增加以下内容end
:
吊舱“谷歌地图”
接下来,翻开终端并运用以下指令导航到包括Feed Me项意图目录:cd
cd ~/Path/To/Folder/Containing/Feed Me
输入以下指令以安装 Google Maps iOS SDK:
卸载重装
您应该会看到类似于以下内容的输出:
下载依靠项
安装谷歌地图 (2.5.0)
运用 SwiftyJSON (4.0.0)
生成 Pods 项目
整合客户项目
现在,您的项目中有GoogleMaps。CocoaPods 不是让日子变得更轻松吗?:]
翻开AppDelegate.swift并将其内容替换为以下内容:
导入UIKit
导入谷歌地图
// 1
让 googleApiKey = "ENTER_KEY_HERE"
@UIApplicationMain
类AppDelegate : UIResponder , UIApplicationDelegate {
变量窗口:UIWindow?
func 应用程序(_ 应用程序:UIApplication,didFinishLaunchingWithOptions 启动选项:[ UIApplicationLaunchOptionsKey:任何] ?)->布尔{
//2
GMSServices .provideAPIKey (googleApiKey)
回来真
}
}
这儿有两个新元素:
- 用于保存您的 Google API 密钥的常量。替换
ENTER_KEY_HERE
为您之前创立的 Google API 密钥。 -
GMSServices
您的应用程序将运用类办法运用 API 密钥实例化 Google 地图服务provideAPIKey()
。
接下来,翻开Main.storyboard以调出 Interface Builder。经过挑选视图工具栏中的第三个选项卡 – 实用程序 – 来调出方针库,然后挑选库工具栏中的第三个选项卡 – 方针库 – 如下面的屏幕截图所示:
找到MapViewController场景并将一个简略UIView
的从方针库拖到MapViewController
视图的大致中心。将视图的布景色彩更改为浅灰色。接下来,运用Editor\Show Document Outline 翻开 Document Outline**并重新排列视图层次结构,使方针树如下所示:
要将这个简略UIView
转换为GMSMapView
,请挑选您刚刚增加的视图,然后经过挑选实用工具工具栏左边的第三个选项卡来翻开身份查看器。将视图的Class更改为GMSMapView
,如下面的屏幕截图所示:
您的MapViewController场景现在应该如下所示:
接下来,您需求增加一些束缚以使地图填满整个屏幕。在 Document Outline 中挑选Map View,然后挑选 Interface Builder 窗口右下角的第二个按钮 —Pin按钮。保证未选中Constrain to margins– 这保证地图将填满屏幕上的一切可用空间 – 并从 superview 的顶部、左边、底部和右侧增加0 (零)空间束缚。
您的 Pin 编辑器应如下所示:
单击Add 4 Constraints将束缚增加到地图视图。 您的MapViewController场景应如下所示,其中灰色区域代表GMSMapView:
在构建和运转项目之前,IBOutlet
为地图视图增加一个。为此,经过挑选编辑器工具栏中的第二个选项卡来调出助手编辑器:
在 Interface Builder 中挑选地图视图,按住Ctrl键并从地图视图中拖出一条线到MapViewController.swift。将呈现一个弹出窗口;将衔接类型设置为Outlet,将称号设置为mapView
.坚持 Type 为GMSMapView
,然后单击Connect:
这将在MapViewController.swift中创立一个GMSMapView
特点,并在 Interface Builder 中自动衔接它。在构建和运转之前,将以下内容增加到文件顶部,之后:import UIKit
导入谷歌地图
构建并运转您的项目;您现在应该看到一张地图,如下所示:
您现在在您的应用程序中运用 Google Maps iOS SDK — 但您能够做的不仅仅是显现根本地图,对吗?:]
获取方位
Feed Me就是寻觅用户邻近的地方,假如不获取用户的方位,您就无法做到这一点。
首要,翻开MapViewController.swift并增加以下特点:
私有 让locationManager = CLLocationManager ()
这将增加并实例化一个CLLocationManager
名为locationManager
.
接下来,找到viewDidLoad()
这两行并将其增加到底部:
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
这将使MapViewController
托付locationManager
和恳求拜访用户的方位。
接下来,翻开Project navigator 顶部的Feed Me项目,挑选**Feed Me方针并转到Info选项卡,挑选**Custom iOS Target Properties部分中的榜首行,然后单击*+*图标以增加新行。
挑选Privacy – Location When In Use Usage Description作为键,挑选String作为类型,然后输入以下文本作为值:
经过拜访您的方位,这个应用程序能够为您找到一个吃饭的好地方。
完结后,它应该如下所示:
在运转应用程序之前,您需求MapViewController
契合CLLocationManagerDelegate
协议。
将以下扩展增加到MapViewController.Swift的底部:
// MARK: - CLLocationManagerDelegate
//1
扩展 MapViewController : CLLocationManagerDelegate {
// 2
func locationManager ( _ manager : CLLocationManager , didChangeAuthorization status : CLAuthorizationStatus ) {
// 3
guard status == .authorizedWhenInUse else {
return
}
// 4
locationManager.startUpdatingLocation()
//5
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
}
// 6
func locationManager ( _ manager : CLLocationManager , didUpdateLocations 方位: [ CLLocation ]) {
guard let location = locations.first else {
return
}
// 7
mapView.camera = GMSCameraPosition(方针:location.coordinate,缩放:15,方位:0,viewingAngle:0)
// 8
locationManager.stopUpdatingLocation()
}
}
依次获取每个编号的谈论:
- 您创立一个
MapViewController
契合CLLocationManagerDelegate
. -
locationManager(_:didChangeAuthorization:)
当用户颁发或撤销方位权限时调用。 - 在这儿,您验证用户在运用应用程序时已颁发您权限。
- 树立权限后,请向方位管理员问询有关用户方位的更新。
-
GMSMapView
有两个关于用户方位的功用:在用户所在的方位myLocationEnabled
制作一个浅蓝色点,而myLocationButton
设置为 时true
,向地图增加一个按钮,点击该按钮时,地图以用户方位为中心。 -
locationManager(_:didUpdateLocations:)
当方位管理器接收到新的方位数据时履行。 - 这会将地图的摄像头更新为以用户当时方位为中心。该类
GMSCameraPosition
聚合一切相机方位参数并将它们传递给地图以进行显现。 - 告知
locationManager
您不再对更新感兴趣;您不想跟随用户,因为他们的初始方位足以让您运用。
构建并运转您的应用程序;加载后,系统会提示您发出警报,问询方位权限。点击答应:
您现在应该会看到以您所在方位为中心的地图。翻滚地图并点击定位按钮,地图将回到您的方位,如下所示:
施行地舆编码
现在您有了用户的方位,假如您能够显现该方位的大街地址,那就太好了。谷歌地图有一个方针能够做到这一点:GMSGeocoder
.这需求一个简略的坐标并回来一个可读的大街地址。
首要,您需求增加一些 UI 以向用户显现地址。
翻开Main.storyboard并增加一个UILabel
到MapViewController场景。保证将标签增加到MapViewController
视图,而不是GMSMapView
.
接下来,翻开特点查看器,并为标签供给以下特点:
- 将对齐设置为center。
- 将线设置为0。令人惊奇的是,这让标签能够根据需求占用尽可能多的行以适应文本。去搞清楚!:]
- 将布景设置为白色,不透明度为 85%。
完结后,标签的特点查看器和场景的方针树应如下所示:
最终给label的左、下、右束缚增加0,如下图:
这会将标签固定到屏幕底部并将其拉伸到整个屏幕宽度。
您的故事板场景应如下所示:
接下来,为标签创立一个出口。挑选Assistant Editor,然后ctrl+从 Document Outline 中的标签拖动到MapViewController.swift。将衔接类型设置为Outlet,将称号设置为addressLabel
并单击Connect。
这会为您增加一个MapViewController
能够在代码中运用的特点:
@IBOutlet 弱 变量地址标签:UILabel!
将以下办法增加到MapViewController
:
私人 函数 reverseGeocodeCoordinate(_ 坐标:CLLocationCoordinate2D){
// 1
让geocoder = GMSGeocoder ()
// 2
geocoder.reverseGeocodeCoordinate(coordinate) { response, error in
guard let address = response ? .firstResult(), let lines = address.lines else {
return
}
// 3
self .addressLabel.text = lines.joined(separator: " \n " )
// 4
UIView .animate(withDuration: 0.25 ) {
self .view.layoutIfNeeded()
}
}
}
再一次,这是每个谈论部分的作用:
- 创立一个
GMSGeocoder
方针以将经纬度坐标转换为大街地址。 - 要求地舆编码器对传递给办法的坐标进行反向地舆编码。然后它验证 type 的呼应中有一个地址
GMSAddress
。这是一个模型类,用于回来的地址GMSGeocoder
。 - 将 的文本设置为
addressLabel
地舆编码器回来的地址。 - 设置地址后,为标签的固有内容巨细的改变设置动画。
每次用户更改他们在地图上的方位时,您都需求调用此办法。为此,您将运用GMSMapViewDelegate
.
在MapViewController.swift的底部增加另一个扩展,如下所示:
// MARK: - GMSMapViewDelegate
扩展 MapViewController : GMSMapViewDelegate {
}
这将声明MapViewController
契合GMSMapViewDelegate
协议。
接下来,将以下代码行增加到viewDidLoad()
:
mapView.delegate = 自我
这使得MapViewController
地图视图的托付。
最终,将以下办法增加到新增加的扩展中:
func mapView(_mapView :GMSMapView,idleAt方位:GMSCameraPosition ) {
reverseGeocodeCoordinate(方位.方针)
}
每次地图中止移动并固定在新方位时都会调用此办法,然后您能够调用该办法对新方位进行反向地舆编码并更新addressLabel
的文本。
构建并运转您的应用程序;你会看到你当时方位的地址——真实的或模拟的——在屏幕底部弹出:
留意到这张图片有什么问题吗?
幸运的是,GMSMapView
为此供给了一个非常简略的解决方案:填充。当填充应用于地图时,一切视觉元素都将根据该填充放置。
回到reverseGeocodeCoordinate(_:)
,并在动画块之前增加这些行:
// 1
let labelHeight = self .addressLabel.intrinsicContentSize.height
self .mapView.padding = UIEdgeInsets (top: self .view.safeAreaInsets.top, left: 0 ,
底部:labelHeight,右侧:0)
现在,将动画块替换为:
UIView .animate(withDuration: 0.25 ) {
//2
self .pinImageVerticalConstraint.constant = ((labelHeight - self .view.safeAreaInsets.top) * 0.5 )
self .view.layoutIfNeeded()
}
这些做两件事:
- 在动画块之前,这会在地图的顶部和底部增加填充。顶部填充等于视图的顶部安全区域插图,而底部填充等于标签的高度。
- 经过调整其笔直布局束缚来更新定位销的方位以匹配地图的填充。
再次构建并运转您的应用程序;这一次,一旦标签可见,Google 徽标和定位按钮将移动到新方位:
移动地图;您会留意到每次地图调整到新方位时地址都会发生改变。让我们增加一个视觉效果来抑制地址改变。
将以下办法增加到GMSMapViewDelegate
扩展中:
func mapView ( _mapView : GMSMapView , willMove手势: Bool ) {
地址标签.lock()
}
每次地图开端移动时都会调用此办法。它会收到一个Bool
告知您移动是源自用户手势(例如翻滚地图)还是源自代码的信息。你调用lock()
onaddressLabel
给它一个加载动画。
当有 时lock()
,也必须有unlock()
。reverseGeocodeCoordinate(coordinate:)
将以下内容增加到’s 闭包的顶部:
自我.addressLabel.unlock()
留意:有关 and 的完整完结lock()
,unlock()
请查看UIViewExtensions.swift。
构建并运转您的应用程序;当您翻滚地图时,您应该会在地址标签上看到加载动画,如下所示:
找东西吃
现在地图现已设置好了,而且你现已把握了用户的方位,是时分让这个用户吃饱了!
您将运用Google Places API查找用户所在方位周围的餐饮场所。Google Places API是一个免费的网络服务 API,您能够运用它来查询以查找任何给定点邻近的机构、地舆方位或其他兴趣点。
Google Maps iOS SDK 为您供给了GMSMarker
在地图上符号方位的类。每个符号方针都包括一个坐标和一个图标图画,并在增加时呈现在地图上。
关于这个应用程序,您需求有关每个符号的更多信息,因而您需求创立一个GMSMarker
.
创立一个新的Cocoa Touch 类,命名它PlaceMarker
并使其成为GMSMarker
.保证挑选Swift作为此文件的言语。
将PlaceMarker.swift的内容替换为以下内容:
导入UIKit
导入GoogleMaps
class PlaceMarker : GMSMarker {
// 1
let place: GooglePlace
// 2
init ( place : GooglePlace ) {
self .place = place
super . 初始化()
方位=地址.坐标
icon = UIImage (命名:place.placeType + "_pin" )
groundAnchor = CGPoint (x: 0.5 , y: 1 )
呈现动画= .pop
}
}
这是一段相对简略的代码:
- 将类型的特点增加
GooglePlace
到PlaceMarker
. - 声明一个新的指定初始化器,它接受 a
GooglePlace
作为其唯一参数,并PlaceMarker
运用方位、图标图画、符号方位的锚点和外观动画完全初始化 a。
接下来,向MapViewController.swift增加别的两个特点,如下所示:
private let dataProvider = GoogleDataProvider ()
private let searchRadius: Double = 1000
您将运用dataProvider
(在GoogleDataProvider.swift中定义)调用Google Places Web API,并searchRadius
确认间隔用户方位多远(以米为单位)来查找地址。
将以下办法增加到MapViewController
:
private func fetchNearbyPlaces (坐标: CLLocationCoordinate2D ) {
// 1
mapView.clear()
// 2
dataProvider.fetchPlacesNearCoordinate(coordinate, radius:searchRadius, types: searchedTypes) { 放置在
地方.forEach {
// 3
let marker = PlaceMarker (place: $0 )
// 4
marker.map = self .mapView
}
}
}
让我们回顾一下您刚刚增加的内容:
- 铲除一切符号的地图。
- 用于
dataProvider
向 Google 查询 中的邻近地址searchRadius
,过滤到用户挑选的类型。 - 遍历完结闭包中回来的成果并
PlaceMarker
为每个成果创立一个。 - 设置符号的地图。这行代码告知地图烘托符号。
这是 64,000 美元的问题:你想什么时分调用这个办法?
首要,用户能够合理地期望在应用启动时看到邻近的地方。
locationManager(_:didUpdateLocations:)
在结尾找到并增加以下代码行:
fetchNearbyPlaces(坐标:location.coordinate)
其次,用户能够更改要在地图上显现的地址类型,因而假如所选类型发生更改,您需求更新查找成果。
找到typesController(_:didSelectTypes:)
以下代码行并将其增加到结尾:
fetchNearbyPlaces(坐标:mapView.camera.target)
最终,您需求为用户供给在方位更改时获取新方位的选项。
翻开Main.storyboard并将方针库中的a 拖到导航栏UIBarButtonItem
的左边。MapViewController
将按钮的 Identifier 更改为Refresh,如下所示:
挑选Assistant Editor并ctrl+从Refresh按钮拖动到MapViewController.swift。挑选Action并命名办法refreshPlaces
。将以下代码刺进新增加的办法中:
fetchNearbyPlaces(坐标:mapView.camera.target)
构建并运转您的项目;您会看到地图周围呈现方位图钉。更改中的查找类型TypesTableViewController
并查看成果怎样改变:
一切这些符号确实为地图增加了一些色彩,但假如没有额定的信息来为用户供给有关固定方位的一些详细信息,它们并没有多大用途。
将以下办法增加到MapViewController.swiftGMSMapViewDelegate
的扩展中:
func mapView(_mapView :GMSMapView,markerInfoContents符号:GMSMarker ) -> UIView?{
// 1后卫let placeMarker = marker as? PlaceMarker else {
回来零
}
// 2
后卫 let infoView = UIView .viewFromNibName( "MarkerInfoView" ) as? MarkerInfoView else {
回来 零
}
// 3
infoView.nameLabel.text = placeMarker.place.name
// 4
if let photo = placeMarker.place.photo {
infoView.placePhoto.image =相片
}其他{
infoView.placePhoto.image = UIImage(命名:“通用”)
}
回来信息查看
}
每次用户点击地图上的符号时都会调用此办法。假如您回来一个视图,那么它会在符号上方弹出。假如nil
回来,则没有任何反响。这是怎样发生的?
- 您首要将点击的符号投射到
PlaceMarker
. -
MarkerInfoView
接下来,您从其笔尖创立一个。该类MarkerInfoView
是UIView
本教程的入门项目附带的子类。 - 然后将地名应用到
nameLabel
. - 查看是否有该地址的相片。假如是这样,将该相片增加到信息视图中。假如没有,请增加通用相片。
在运转应用程序之前,您需求保证方位图钉没有掩盖信息窗口。将以下办法增加到GMSMapViewDelegate
扩展中:
func mapView ( _mapView : GMSMapView , didTap marker : GMSMarker ) -> Bool {
mapCenterPinImage.fadeOut( 0.25 )
回来 false
}
此办法只是在点击符号时躲藏定位销。该办法回来false
以指示您不想在点击符号时掩盖默许行为 – 以符号为中心使地图居中。
明显,该引脚需求在某个时分重新呈现。将以下内容增加到结尾mapView(_:willMove:)
:
假如(手势){
mapCenterPinImage.fadeIn( 0.25 )
mapView.selectedMarker = nil
}
这将查看移动是否源自用户手势;fadeIn(_:)
假如是这样,它会运用该办法取消躲藏定位销。将地图设置selectedMarker
为 nil 将删去当时呈现的infoView
.
最终,将以下办法增加到GMSMapViewDelegate
扩展中:
func didTapMyLocationButton (用于 mapView : GMSMapView ) -> Bool {
mapCenterPinImage.fadeIn( 0.25 )
mapView.selectedMarker = nil
回来 false
}
该办法在用户点击定位按钮时运转;然后地图将以用户的方位为中心。再次回来false
表示它不会掩盖点击按钮时的默许行为。
构建并运转您的应用程序;挑选一个符号,您会看到方位图钉淡出。翻滚地图会封闭infoView
并带回图钉:
就是这样,你做到了!您现在具有一个功用完全的 Google 地图应用程序。:]
结论
请记住,在您能够运转这个已完结的项目之前,您需求刺进您的 API 密钥,就像您在本教程开端时所做的那样。
我在这儿的意图不是要让你信任 Google Maps iOS SDK 比 Apple 自己的 MapKit 更好;可是,以下是 Google 地图的一些长处和缺点:
长处
- Google 对 SDK 的频繁更新。
- 跨平台(iOS 和 Android)应用程序的一致体验。
- 谷歌地图一般更详细,尤其是在美国以外。例如:
缺点
- 与 Google Maps 不同,MapKit 是 iOS 原生的,这意味着它始终与 iOS 同步,而且开箱即可与 Swift 一同运用。
- 与 MapKit 相比缺乏稳定性。
- MapKit 与 CoreLocation 和 CoreAnimation 有更好的集成。
您能够运用教程中的一切代码部分下载最终项目。
这儿也推荐一些面试相关的内容!
-
① BAT等各个大厂iOS面试真题+答案大全
-
② iOS中高级开发必看的热门书籍(经典必看)
-
③ iOS开发高级面试”简历制作”辅导
-
④ iOS面试流程到基础知识大全