324
14
多媒体、联系人、位置和通知
本章将增强这个
iOS
应用,让附件系统支持更多的文件类型,再让应用支持通知。我们
将支持位置、音频、视频和联系人,还将支持本地通知,提醒用户该写笔记了。
Notes
应用中,各个附件对应添加到文档的
Attachments
目录中的一个文件,而且由各
自的视图控制器管理。鉴于这个应用的架构,为了支持不同的附件类型,我们只需创建
新的视图控制器,然后在
DocumentListViewController
中现有的方法里添加一些代码,
打开相应附件类型对应的视图控制器。
下面先从包含地理位置信息的附件开始。
14.1
位置附件
iOS
设备中有很多有用的传感器,其中最有用的是
GPS
。不过,需要定位设备时
iOS
不光依赖
GPS
iOS
有很多功能,能更精确、更快速地确定位置。
Core Location
框架提供了一系列位置相关的功能,从快速准确地找出当前位置,到
监视特定区域的出入口、搜寻蓝牙信号,以及位置大幅度变化警告等,不一而足。
这里,我们只会用到
Core Location
框架的一小部分功能。如果想进一步学习
请阅读
Apple
文档中的“
Location and Maps Programming Guide
”(
http://apple.
co/22UHNXD
)。
iOS
设备确定它在地球上的位置有三种方式:
使用定位无线电,从轨道卫星接收
GPS
GLONASS
信号。
多媒体、联系人、位置和通知
325
使用
WiFi
位置,
iOS
设备使用一个包含
WiFi
热点地理位置的众包数据库,根据设
备可以搜寻的热点估计设备在世界上的位置。
使用基站位置,这与
WiFi
位置的原理基本相同,但是使用为手机提供信号覆盖的基
站。
Core Location
系统的设计方式决定了,我们无需了解设备定位的细节。我们只需让
iOS
设备开始追踪用户的位置,系统会把位置返回给我们。系统会根据你指定的精度确定该
使用什么硬件。
用户的位置是隐私,没有用户的授权,应用无法访问。而用户没有义务赋予你这个
权限。因此,处理用户位置的应用都要做好用户拒绝的准备。
接下来,添加为文档附加位置的功能。位置附件是包含经纬度的
JSON
文件,可以使用
MapKit
在地图上显示。
JSON
文件不是专门针对位置的标准或格式,我们使用它只是为
了便利。目前没有标准的位置文件格式,使用包含少量数据的
JSON
是个不错的选择。
MapKit
Apple
创建,提供了功能完善的地图,可以在我们的应用中使用。地图中可以
包含
iOS
OS X
自带的“地图”应用的一切功能,从街景到卫星图,到
3D
建筑等。
MapKit
还支持自定义注解,原生支持缩放和平移。
自定义的注解可以是单个点(经纬度),也可以是图层,由多个点组成一个形状。注解
和图层的行为与预期一样,而且不只是呆板的子视图,当用户平移、缩放或以其他方式
操作地图时,它们会相应地移动或改变大小。
即便地图上有数百个注解或图层,
MapKit
的性能依旧很好。
首先设置应用,让它使用位置服务。
1.
打开应用的
Info.plist
文件。
2.
在字典中添加一个字符串键
NSLocationWhenInUseUsageDescription
,把它的值设为
字符串
"We
ll use your position to show where you are on the map"
(我们将在地图
上显示你的位置)。当应用首次定位时,会在一个弹出框中显示这个字符串。
326
14
如非必要,切勿定位用户的位置。
Apple
不赞成这么做,而且用户会怀疑你的动机。
要谨慎对待访问用户位置这件事。
3.
打开
Assets.xcassets
文件。
4.
Location.pdf
Current Location.pdf
拖曳到图像列表中。
5.
打开
Document.swift
6.
把下述代码添加到
thumbnailImage
方法中,如果是
JSON
附件,返回
Location
像:
func thumbnailImage() -> UIImage? {
if self.conformsToType(kUTTypeImage) {
//
如果是图像,作为
UIImage
对象返回
//
确保可以访问文件的内容
guard let attachmentContent = self.regularFileContents else {
return nil
}
//
尝试把文件的内容转换成文本
return UIImage(data: attachmentContent)
}
> if self.conformsToType(kUTTypeJSON) {
> //
用于存放位置的
JSON
文件
> return UIImage(named: "Location")
> }
>
//
不知道是什么类型,返回
nil
return nil
}
我们添加的代码让
NSFileWrapper
返回刚刚添加到静态资源目录中的
Location.pdf
像。
接下来,添加一个视图控制器,用于添加和查看位置。首先编写代码,然后设计界面。
1.
打开“
File
”菜单,选择“
File
”→“
New
”。
2.
选择“
Cocoa Touch Class
”,然后单击“
Next
”。
3.
把这个新类命名为
LocationAttachmentViewController
把它设为
UIViewController
的子类。
多媒体、联系人、位置和通知
327
4.
打开
LocationAttachmentViewController.swift
5.
在文件顶部导入
MapKit
CoreLocation
两个框架:
import MapKit
import CoreLocation
6.
import
语句下面添加下述代码:
let defaultCoordinate =
CLLocationCoordinate2D(latitude: -42.882743, longitude: 147.330234)
无法确定用户的位置时,将使用这个坐标。
7.
LocationAttachmentViewController
符合
AttachmentViewer
MKMapViewDelegate
协议:
class LocationAttachmentViewController: UIViewController,
AttachmentViewer, MKMapViewDelegate {
8.
在类中添加一个
MKMapView
类型的
outlet
,名为
mapView
@IBOutlet weak var mapView : MKMapView?
9.
添加
AttachmentViewer
协议所需
attachmentFile
document
性:
var attachmentFile : NSFileWrapper?
var document : Document?
10.
打开
Main.storyboard
,拖曳一个
UIViewController
11.
打开“
Identity Inspector
”,把视图控制器的类改为
LocationAttachmentViewController
12.
拖曳一个
MKMapView
到视图控制器的界面中。
13.
添加约束,让地图视图占满整个界面,在顶部留出
20
点宽的间隙,用于显示状态栏。
14.
打开“
Attributes Inspector
”,勾选“
Shows User Location
”复选框。
15.
按住
Control
键,从地图视图拖曳到视图控制器上。在弹出的菜单中选择
delegate
”。
16.
再次按住
Control
,从视图控制器拖曳到地图视图上。在弹出的菜单中选择
mapView
”。
地图视图添加好了,下面要添加一个工具栏,里面有个按钮,轻点后缩放地图,直达用
户的当前位置,但是仅当能确定用户的位置时才这么做。否则,把按钮设为浅色。
328
14
位置跟踪系统无法保证一定能找出用户的位置。用户可能没有授权(本节处理),
但是除此之外,定位硬件也可能根本无法锁定用户的位置。处理位置的应用要优雅
地处理这些失败情况。
1.
拖曳一个
UIToolbar
到界面中,放到屏幕的底部。让它占满整个屏幕的宽度,然后
添加约束,把它固定在底部,左右两边与边界贴合。
2.
选择工具栏左侧那个按钮,打开“
Attributes Inspector
”。
3.
把按钮的图像设为“
Current Location
”。
现在,工具栏看起来如图
14-1
所示。
14-1
更新后的工具栏
4.
在辅助编辑器中打开
LocationAttachmentViewController.swift
5.
把工具栏中的那个按钮连接到
LocationAttachmentViewController
中的一个新
outlet
上,名为
showCurrentLocationButton

Get Swift学习手册 now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.