iOS开发初学者入门 | 第八章:地图和位置

在这一章节中,你将会学到在你的app中如何使用iPhone中的GPS。你将会学会如何获得用户的位置,同时在地图上标注出位置。本章内容涵盖了 地图套件(Map Kit)和苹果公司提供的地图、方向框架。通过学习本章节的内容,你马上就可以搞定基于位置定位的应用。

提供用户的位置信息是开发iOS应用最激动人心的特性,在地图上显示用户的位需要两个步骤。

第一步用Core Location来收集用户的位置。Core Location是一系列类的集合,通过设备的GPS和蜂窝获取位置信息,还能借助WIFI获取用户信息。Core Location 是由苹果公司提供的众多frameworks中的一个。Frameworks是一组类的集合,为具体的某个任务而设计的一套工具。我们现在用Core Location举一个例子,Core Location是为了处理用户位置信息而设计的一个framework。Core Data是为了处理数据而设计的一个framework。这些framework是可选的,因此需要先把这些框架导入到工程当中后,才能使用这些框架。

第二步是在地图中标注出用户的位置。苹果公司提供了Map Kit框架,帮助我们绘制和管理地图。在Xcode 6中导入框架非常容易。首先Project Navigator中点击项目名称,点击名为Capabilities的tab选项按钮,向下滚动找到Maps。将地图的开关键处于On的状态,这时MapKit框架已经添加到工程中了。现在虽然能够在工程中找到MapKit,但是导入流程还没有完成。MapKit还需要导入controller file中。我们下列一行代码完成导入工作:

import MapKit

这样,MapKit类和协议就导入到controller文件中了。MapKit中的类和协议都是以MK开头的。

Page 213

Core Location

正如之前所说的,Core Location是一系列查找用户位置的类的集合。Core Location中有三个检测用户位置的方法。第一个方法是Significant-Change Location。这个方法能够节约电池电量,它只在用户的位置明显改变时才会更新位置。第二个方法是Location Services,可以自主规定定位更新的规则。最后一种方法是Regional Monitoring方法,使用附近的地理区域边界或者Bluetooth beacons来定位。本书主要介绍第二种方法:Location Services,它是最常用到的方法。

更多信息请参考苹果公司的Location and Maps Programming Guide

获取用户位置需要使用Core Location框架,当你把Maps capabilities开关切换成On(开)状态时,Xcode并没有自动导入Core Location框架,需要我们手动导入,请看以下四个步骤:

  1. 点击Project Navigator上的蓝色工程图标;
  2. Editor显示工程的详细信息,滑倒最下方;
  3. 在Link Binary with Libraries下方点击Add;
  4. 选择Core Location,然后点击Add。

Core Location框架就会添加到Project Navigator中,我们还需要在controller中写一行代码才能获取此框架:

import CoreLocation
手机用户的位置非常耗费电量,它比其他的任务需要更多的电池电量和天线频率,所以确保你的App只有在需要位置时才获取位置,一旦获取到位置,就把这个功能关掉,如果将来还需要地理位置,可以使用定期更新功能

在获取用户位置之前,很重要的一件事是先检查定位服务是否可用。定位服务无法使用可能是由于以下几种情况:

  • 用户在设置中关闭了Location Services(定位服务)。
  • 用户禁止你的App使用Location Services(定位服务)。
  • 设备处于飞行模式或者连接不了网络。

Page 214 | Chapter 8 : Maps and Location

Core Location提供了名为locationServicesEnabled的方法来检查设备的定位服务是否可用,locationServicesEnabled方法通过布尔类型返回值来确定定位服务是否可用,true可用,false不可用。

Requesting User Location

通过CLLocationManager类来请求用户位置。首字母CL代表Core Location。The location manager用于收集参数和开启定位服务。创建CLLocationManager对象和创建其他的对象类似。举例说明:

var locationManager: CLLocationManager = CLLocationManager()

CLLocationManager有一些属性是必须要设置的。

desiredAccuracy属性是枚举类型,枚举,就是用一个关键词代表一个数字。枚举有点像是多选题,你必须从选项中挑选出一个值来。desiredAccuracy属性有下面一些值:

kCLLocationAccuracyBest
最精准的定位,也是最消耗电量的选项
kCLLocationAccuracyNearestTenMeters
精准度在十米范围内
kCLLocationAccuracyHundredMeters
准确度在一百米范围内
kCLLocationAccuracyKilometer
精确度在一千米范围内
kCLLocationAccuracyThreeKilometers
精确度在三千米范围内

精准度越高,电量消耗越大。我们要选择能够满足最低要求的精准度级别。如果是像Google地图之类的App来追踪用户的位置,那么kCLLocationAccuracyNearestTenMeters或者kCLLocationAccuracyHundredMeters就可以满足我们的需求。如果App只需提供用户所在城市,像是Twitter中的定位,kCLLocationAccuracyKilometer或者kCLLocationAccuracyThreeKilometers就可以满足我们的需求。大多数情况下,一般不需要kCLLocationAccuracyBest

设置desiredAccuracy属性的方法和设置其他对象的属性一样:

locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters

Core Location | Page 215

CLLocationManager也需要delegate属性。CLLocationManage delegate遵循CLLocationManagerDelegate协议。无论何时出现了位置更新或者出现错误,delegate都会接收到警告。为了接收这些警告,delegate必须通过CLLocationManagerDelegate协议与警报保持沟通。controller必须声明遵循协议,将CLLocationManagerDelegate添加到类的顶部:

class ViewController: UIViewController, CLLocationManagerDelegate

想要接收定位警高,要使用locationManager(_:,didUpdateLocations:)方法。每当定位信息改变的时,这个方法就会被调用:

func locationManger(manager: CLLocationManager!,didUpdateLocations locations: [AnyObject]!) {
    println("Location found")
}

想要在任何时候都能收到Core Location的错误警告,需要使用locationManager(_: didFailWithError:)方法:

func locationManager(manager: CLLocationManager!, didFailWithError error:NSError!) {
    println("Error!")
}

一旦遵循协议并使用其中的方法后,就必须要设置delegate的属性:

locationManager.delegate = self

在激活定位服务之前, 用户必须同意app使用用户的位置信息。定位服务有两种批准类型。第一种是requestWhenInUseAuthorization;授权App仅限前台运行的时使用位置信息。 第二种是requestAlwaysAuthorization. 授权App在前台还是后台运行都可以获取用户的位置信息,第二个授权都会给app提供追踪用户位置的能力。调用授权的方法是:

locationManager.requestWhenInUseAuthorization()

locationManager.requestAlwaysAuthorization()

获得授权后,调用startUpdatingLocation()方法开启定位服务:

locationManager.startUpdatingLocation()

这样,locationManager会根据相关要求开始追踪并返回用户位置信息。

Page 216 | Chapter 8 : Maps and Location

locationManager (_:, didUpdateLocations:)方法会提供CLLocation数组,按照出现前后顺序排列。数组中至少会有一个对象。数组中的每一个对象都是是一个CLLocation。CLLocation这个类为具体的位置整理组织CLLocationManager的位置数据。CLLocation跟踪地理坐标,海拔,速度,方向,甚至包括定位准确度。CLLocation拥有许多有用的属性:

coordinate
CLLocationCoordinate2D, 纬度坐标和经度坐标
altitude
海拔高度,单位:米
timestamp
获取到数据时的时间和日期
description
用字符串的格式返回CLLocation,可以用print()打印出来

请牢记,一旦你获得了你需要的信息,必须停止定位服务功能。为了停止这些服务,在CLLocationManager中调用stopUpdatingLocation() :

manager.stopUpdatingLocation()

举个例子,在locationManager( manager: ,didUpdateLocations:)方法中获取位置后,常常会停止定位服务。之前在CLLocationManager中创建的那些变量非常适合处理目前的这种情况。

**明白了!** iOS 8模拟器在模拟Core Location时会出现一些前后不一致的行为。如果定位服务没有调用,在Info.plist文件中添加三个键: NSLocationWhenInUsageDescription NSLocationAlwaysUsageDescription NSLocationUsageDescription 每个键对应的值设置成Always或者When in Use 这三个键值会帮助开启定位服务

Core Location | Page 217

Map Kit

Map Kit框架提供地图和方向,地图可以展示到街道级别的信息,3D建筑,卫星图像,或者将两者组合起来。地图自动响应缩小、放大、平移、倾斜等手势动作,还能在地图上标注点同时加上注解。

MKMapView

Map Kit提供MKMapView视图类来展示地图,MKMapView可以展示地图,管理用户的输入信息,展示自定义注释。

MKMapView也有一个delegate属性。和CLLocationManager的delegate属性一样,MKMapView的delegate也能接收updates。MKMapView delegate需要遵循MKMapViewDelegate协议。设置delegate的方法是,从Storyboard的Editor中,将Map View用Control拖动法拖动到Document Outline中的View Controller文字上,然后弹出一个菜单,点击菜单中的delegate,这样就在相关界面上设置好了delegate。

MKMapView有很多方便的属性和方法。举了例子,MKMapView不用添加任何代码就可以在地图上展示用户地理位置。我们把属性设置showsUserLocationtrue,就可以在地图上显示用户信息了:

myMapView.showsUserLocation = true

用户的位置将会在地图上用一个蓝点标注出来。

一般我们把用户所在位置设置为地图的中心点。如果想移动重新设置地图中心点,需要设置centerCoordinate属性,centerCoordinate属性需要CLLocationCoordinate2DCLLocationCoordinate2D是经度和纬度的坐标,被打包成一个单独的变量。通过CLLocationCoordinate2DMake方法创建CLLocationCoordinate2D

var coordinates: CLLocationCoordinate2D = CLLocationCoordinate2DMake(100,100)

有时候我们会在地图上放大位置,当region属性设置好后,放大后图像会自动调整。region属性需要MKCoordinateRegion对象,然而,大部分情况下,比起创建新的对象,编辑当前的region对象会更简单一些:

var updatedRegion: MKCoordinateRegion = myMapView.region
updatedRegion.span.longitudeDelta = updatedRegion.span.longitudeDelta * 2.0
updatedRegion.span.latitudeDelta = updatedRegion.span.latitudeDelta * 2.0 
myMapView.region = updatedRegion

Page 218 | Chapter 8 : Maps and Location

longitudeDeltalatitudeDelta都是span的一部分,span是面积有多大,以centerCoordinate为中心可展示的宽度和高度。

Directions (方向)

Map Kit还能够在App中提供建议规划路线导航功能。MKDirections API可以根据苹果服务器的计算提供线路方向。有步行线路规划,驾驶线路规划,花费的时间,和其他可选的路线。地图上的每个点用MKMapItem表示,MKMapItem包含了地图上有关地点的所有信息,这些信息包括地图位置,坐标值,地点名称等数据。MKMapItem还能传到地图应用上,使用地图应用上更多高级功能。

创建MKMapItem最简单的方法是使用mapItemForCurrentLocation方法,这个方法获取用户的位置然后根据位置创建MKMapItem:

var mapItem: MKMapItem = MKMapItem.mapItemForCurrentLocation()

MKMapItem类有一些便利的属性。name属性是一个字符串,提供地点的描述性名称。phoneNumber属性也是字符串,存储这个位置的电话号码。URL属性存储位置的网址。

MKMapItem创建后,就可以轻松的把位置传递到地图应用上,使用导航功能。openMapWithItems: launchOptions方法可接收一个数组,数组中包括包括一至多个的MKMapItem。通过launchOptions,这么些items就会被映射到地图应用上。MKLaunchOptionsDirectionsModeKey让地图应用基于两个点来提供规划路线。

Plotting Points (绘制点、标注点)

苹果公司提供了一个在地图上绘制点的方法,叫annotations(注解)。annotations是可以定义一个地方或者一个点。它常常用于突出感兴趣的地点,提供更多细节。annotations也拥有一个可选标注气泡(optional callout bubble)。气泡代表一些位置的名字和地址那样的信息。气泡也是可点击的,可以像button(按钮)那样接收用户的动作。

annotations由两部分组成,注解对象(annotation object)和注解视图(annotation view)。annotation object是一个轻量级对象,管理annotation中的数据。annotation object是从MKPointAnnotation类中创建的。annotation view是从MKPinAnnotationView类中创建的。annotation view用来在地图上标注pin(大头针)。

Map Kit | Page 219

三个步将annotation添加到MKMapView中。第一步是为感兴趣的地点创建一个MKPointAnnotation:

var point = MKPointAnnotation()
point.coordinate = CLLocationCoordinate2DMake(37.7756, -122.4193)
point.title = "San Francisco"

接下来,遵循MKMapView协议,回应mapView(_: viewForAnnotation:)方法,此方法可以回收利用annotation view,就像是table view中也有方法可以重复利用cell:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!)-> MKAnnotationView! {
    var pin = MKPinAnnotationView(annotation: annotation, reuseIdentifier:"pinIdentifier")
    return pin
}

最后,调用addAnnotation方法,这样,就把annotation添加到地图中了:

mapView.addAnnotation(point)

现在,我们来搞定你第一个使用了地图App吧。

Exercise: Adding Maps to the Passport App

练习请见此链接

Page 220| Chapter 8 : Maps and Location

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容