给护照App增加地图功能~第八章练习Adding Maps to the Passport App

在本章的练习中,我们要给前几章中的Passport App增加地图功能,添加一个Map View,在每个去过的国家上方都出现一个大头针(见图8-1)。当用户点击Countries Visited界面右上角的Map按钮时,出现地图界面。

图8-1

Page 220 | Chapter 8: Maps and Location

首先我们打开Passport.xcodeproj文件,点击Project Navigator中的工程名字Passport,点击Capabilities,往下滑,找到Maps,打开开关(见图8-2)。

图8-2

Exercise: Adding Maps to the Passport App | Page 221

在Project Navigation中会出现MapKit.framework,接着选择顶部菜单栏File -> New -> File,选择iOS下的Cocoa Touch Class,点击Next。

Subclass of选择UIViewController,Class名字为MapViewController(见图8-3),语言Swift,点击Next,保存在Passport文件夹中,点击Create。新文件MapViewController.swift出现在屏幕上。

图8-3

Page 222 | Chapter 8: Maps and Location

选中文件中的绿色注释代码,删掉。注意不要误删最后的右大括号,删掉didReceiveMemoryWarning方法。

打开Main.storyboard(见图8-4),首先确认当前处于“Any,Any”这个size class下,如果不是,点击Size class,选择中间的那个格子(见图8-5)。

图8-4
图8-5

Exercise: Adding Maps to the Passport App | Page 223

隐藏Project Navigator和Document Outline,打开Inspector,界面调整到Table View Controller Scene右侧(见图8-6)。

图8-6

Page 224 | Chapter 8: Maps and Location

在Object Library中拖拽一个View Controller,放到Table View Controller Scene右侧,然后在Object Library搜索框中输入map,拖拽一个Map View到View Controller中(见图8-7)。把Map View四周拖拽变大直到覆盖整个View。

图8-7

选中Map View,从顶部菜单栏选择Editor -> Pin -> Leading Space to Superview;再次选中Map View,从顶部菜单栏选择Editor -> Pin -> Trailing Space to Superview;再次选中Map View,从顶部菜单栏选择Editor -> Pin -> Top Space to Superview;再次选中Map View,从顶部菜单栏选择Editor -> Pin -> Bottom Space to Superview。这样Map View就能够适配任何尺寸的设备了。

清空Object Library的搜索框,然后输入BarButton,选择Bar Button Item拖拽到Table View Controller Scene中,双击Bar Button Item,输入Map。按住Control键,点击Map按钮,拖拽到刚刚设置的有Map的View Controller上,弹出一个选项框,选择show选项(见图8-8)。

图8-8

在Map scene中,出现了一个navigation bar。

Exercise: Adding Maps to the Passport App | Page 225

点击其中的MKMapView,Control拖拽法拖到上方的黄色圆圈(见图8-9)。

图8-9

弹出一个小的菜单,选择delegate选项(见图8-10)。这样,MapViewController.swift文件能够收到MKMapView的委托通知(delegate update)了。

图8-10

Page 226 | Chapter 8: Maps and Location

storyboard的设置几乎快要完成了。必须把Map scene和MapViewController.swift文件关联起来。点击Map scene上的黄色圆圈,接着打开Identity Inspector,工具栏中点击第三个图标,在Class这输入MapViewController(见图8-11)。这样,Map scene和MapViewController.swift文件就关联起来了。

图8-11

隐藏Inspector打开Assistant Editor,点击Assistant Editor上方的Preview,选择Automatic,Control拖拽法把MKMapView拖到MapViewController.swift文件中(见图8-12),弹出菜单(见图8-13)。

图8-12
图8-13

Exercise: Adding Maps to the Passport App | Page 227

Name一栏输入myMapView,点击Connect,创建了一个IBOutlet连接。不过这里出现了红色报错,出现错误是因为Map Kit framework还没有引入到MapViewController类中,输入import MapKit即可(见图8-14)。

图8-14

Page 228 | Chapter 8: Maps and Location

这时报错提示消失了。不管什么时候map出发事件,MapViewController都会收到delegate update。当然我们还需要让MapViewController使用MKMapView Delegate协议,修改增加下列代码:

class MapViewController: UIViewController, MKMapViewDelegate {

这样声明MapViewController会遵守MKMapView Delegate协议,把鼠标放到viewDidLoad方法中的super.viewDidLoad()下方。

在viewDidLoad方法中,你需要创建四个MKPointAnnotation对象,这四个对象能存储大头针需要出现的位置和显示文案。在viewDidLoad方法中添加下列代码:

let italy = MKPointAnnotation()
italy.coordinate = CLLocationCoordinate2DMake(41.8947400,12.4839000)
italy.title = "Rome, Italy"

let england = MKPointAnnotation()
england.coordinate = CLLocationCoordinate2DMake(51.5085300, -0.1257400)
england.title = "London, England"

let norway = MKPointAnnotation()
norway.coordinate = CLLocationCoordinate2DMake(59.914225, 10.75256)
norway.title = "Oslo, Norway"

let spain = MKPointAnnotation()
spain.coordinate = CLLocationCoordinate2DMake(40.41694, -3.70081) 
spain.title = "Madrid, Spain"

Exercise: Adding Maps to the Passport App | Page 229

这样就创建了MKPointAnnotation对象。第一个行代码把常量italy设置为一个MKPointAnnotation对象,coordinate属性可以设置具体的位置,CLLocationCoordinate2DMake方法获取位置的经度和纬度,然后转换成一组coordinate。最后title属性是郭靖和城市的名字,当用户点击地图上的大头针时,出现title。

四个MKPointAnnotation对象要添加到Map中,不过首先需要添加到数组中,创建一个数组,存储这四个位置,把下列代码添加到span MKPointAnnotation后面:

let locations = [italy, england, norway, spain]

这样创建了名为locations的数组,数组中有四个MKPointAnnotation对象。
添加到map中方法使用addAnnotations()方法,在之前的代码下方添加下列代码:

myMapView.addAnnotations(locations)

这行代码能够发送消息给myMapView,让其把italy,england,span和norway的地点添加到地图中。然而,我们还需要做一件事,所有的MKPointAnnotation都必须与MKPinAnnotationView配对,我们用mapView(_: viewForAnnotation:)方法来配对。把鼠标光标放到viewDidLoad方法外面的下方,输入下列代码:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!)-> MKAnnotationView! {

}

当一个MKPointAnnotation添加到地图中后,这个方法回应MKMapView Delegate触发事件。这样MKPointAnnotations和MKPinAnnotationViews之间完成匹配工作。在mapView(_: viewForAnnotation:)方法里面,添加下列代码(见图8-15):

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

图8-15

Page 230 | Chapter 8: Maps and Location

每次annotation添加到地图中时,这个方法都会被调用。第一行创建变量pin,赋值 MKPinAnnotationView。 MKPinAnnotationView创建成功,annotation属性设置为annotation参数。

当前的MKPinAnnotation有参数值annotation,这样可能会造成困惑,然而,我们经常见过统一的名字使用两次代表不同的变量。关键是认识到annotation属性和annotation参数值的去边,知道两者的区别才是关键。annotation属性,在MKPinAnnotationView中可用,用来定位地图大头针的位置。而annotation参数值,是MKPinAnnotation匹配MKPinAnnotationView。

MKPinAnnotationView中的reuseIdentifier设置为pinIdentifier,这样可以回收利用MKPinAnnotationView,尤其是地图中的大头针特别多时,回收利用会有明显的优势。最后,MKPinAnnotationView的canShowCallout属性值设置为true。这样当大头针被用户点击时,能够出现泡泡效果。

把鼠标光标放到myMapView.addAnnotations(locations)下方,添加下列代码:

var myRegion = MKCoordinateRegionMakeWithDistance(italy.coordinate,5500000,5500000)
myMapView.setRegion(myRegion, animated: true)

Exercise: Adding Maps to the Passport App | Page 231

第一行是创建名为myRegion的变量,设置只为MKCoordinateRegion。可以用MKCoordinateRegionMakeWithDistance()方法创建MKCoordinateRegion。这个方法首先找到一个点,然后围绕这个点画出一块区域,这个区域就是地图呈现的区域。

这第二行代码是给map发送消息,告诉Map把区域设置成新创建的myRegion,true表示可以放大缩小,运行程序,这次模拟器选择iPhone 6 Plus(见图8-16)。

图8-16

现在当App启动后,大头针就会自动出现在对应的国家上了。结束运行,选择iPad Air模拟器,运行看一下效果(见图8-17)。

图8-17

Page 232 | Chapter 8: Maps and Location

如果App没有按照你想要的结果运行,或者程序有了错误或警告,不要太担心,学习的最佳方式就是试错,熟能生巧,到我们的网站上下载示例代码,对比一下代码,多试几次,直到搞定这个程序为止。

Exercise: Adding Maps to the Passport App | Page 233

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

推荐阅读更多精彩内容