356
14
14-4
启用
Audio, AirPlay and Picture in Picture
后台模式
completion: nil)
}
})
segueName = nil
我们把应用的音频会话分类设为
AVAudioSessionCategoryPlayback
,告诉系统这个
应用能播放内容。这会给播放器启用画中画模式。
现在,播放视频时,用户可以轻点画中画按钮,把视图缩放到角落。即便你离开这个应
用了,那个视图依然在那里。
14.4
联系人附件
接下来让文档支持联系人附件。联系人以
vCard
文件表示,使用
Contacts
ContactsUI
框架实现。添加联系人使用
CNContactPickerViewController
,查看联
系人附件使用
CNContactViewController
。为了加载和保存联系人文件,我们将使用
CNContactVCardSerialization
用户的联系人是隐私,是敏感信息,但愿这是显而易见的共识。因此,如果想自
由访问联系人,要请求权限,这与摄像头、麦克风和位置服务一样。然而,使用
CNContactPickerViewController
时不用这么做。这个视图控制器完全在系统的控制之
下,作为应用和联系人列表的中间人。呈现这个视图控制器时,连截图都不允许。因此,
用户可以放心选择联系人,把它提供给应用处理。
多媒体、联系人、位置和通知
357
获得联系人之后,我们将使用
CNContactViewController
呈现它。这个视图控制器提供
UI
与“通讯录”应用中的一样,而且能显示相应联系人的详情。
最后,为了从硬盘中读取联系人,以及把联系人写入硬盘,我们要把
CNContact
对象转
换成某种数据格式。为此,我们将使用
CNContactVCardSerialization
,它使用
vCard
式读写联系人数据。
首先,为这个新附件类型添加基本的支持。
1.
打开
Assets.xcasset
,把
Contact
图像添加到静态资源目录中。
2.
打开
Document.swift
,把下述代码添加到
NSFileWrapper
扩展的
thumbnailImage
法中:
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")
}
if (self.conformsToType(kUTTypeAudio)) {
return UIImage(named: "Audio")
}
if (self.conformsToType(kUTTypeMovie)) {
return UIImage(named: "Video")
}
> if self.conformsToType(kUTTypeContact) {
> return UIImage(named: "Contact")
> }
//
不知道是什么类型,返回
nil
return nil
}
这里的做法与之前一样:如果是某种联系人文件,返回
Contact.pdf
图像。
358
14
3.
打开
DocumentViewController.swift
4.
在文件顶部导入
Contacts
ContactsUI
框架:
import Contacts
import ContactsUI
Contacts
框架包含处理联系人本身的对象,而
ContactsUI
框架包含呈现和处理联系
人的视图控制器。
5.
addAttachment
方法中为动作附着对话框添加一个
Contact
项目:
actionSheet.addAction(UIAlertAction(title: "Contact",
style: UIAlertActionStyle.Default, handler: { (action) -> Void in
self.addContact()
}))
6.
DocumentViewController
类添加一个扩展,让它符合
CNContactPickerDelegate
协议。这个扩展还包含创建和显示联系人选择器的方法。
extension DocumentViewController : CNContactPickerDelegate {
func addContact() {
let contactPicker = CNContactPickerViewController()
contactPicker.delegate = self
self.shouldCloseOnDisappear = false
self.presentViewController(contactPicker,
animated: true,
completion: nil)
}
func contactPicker(picker: CNContactPickerViewController,
didSelectContact contact: CNContact) {
do {
if let data = try? CNContactVCardSerialization
.dataWithContacts([contact]) {
let name = "\(contact.identifier)-" +
"\(contact.givenName)\(contact.familyName).vcf"
try self.document?.addAttachmentWithData(data, name:name)
self.attachmentsCollectionView?.reloadData()
}
} catch let error as NSError {
NSLog("Failed to save contact: \(error)")
}
}
}
多媒体、联系人、位置和通知
359
addContact
方法创建一个
CNContactPickerViewController
,并把它的委托对象设为
DocumentViewController
。就在这个扩展中,我们实现了作为委托对象所需的一个重
要方法
contactPicker(_, didSelectContact:)
用户在联系人选择器中选择一个联系人时调用这个方法。首先,我们使用
CNContactVCardSerialization
类尝试把用户选中的联系人转换成
vCard
格式。如果
成功转换,使用卡片中的信息(唯一的标识符字符串、用户的名字和姓)为联系人
创建一个文件名,再传给
Document
类,保存联系人附件。
7.
最后,把下述代码添加到
collectionView(_, didSelectItemAtIndexPath:)
法中,
添加查看联系人功能:
} else if attachment.conformsToType(kUTTypeContact) {
do {
if let data = attachment.regularFileContents,
let contact = try CNContactVCardSerialization
.contactsWithData(data).first as? CNContact {
let contactViewController =
CNContactViewController(forContact: contact)
let navigationController =
UINavigationController(rootViewController:
contactViewController)
contactViewController.navigationItem
.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .Done,
target: self,
action: "dismissModalView")
self.presentViewController(navigationController,
animated: true, completion: nil)
}
} catch let error as NSError {
NSLog("Error displaying contact: \(error)")
}
segueName = nil
这里,我们从附件中获取数据,尝试使用
CNContactVCardSerialization
vCard
格式的数据转换成便于处理的
CNContact
对象。然后,使用这个对象准备
CNContactViewController
,用于呈现联系人。然而,
CNContactViewController
自身没有关闭自己的机制。因此,我们要创建一个
UINavigationController
在导航栏中添加
Done
”按钮。轻点这个按钮后会调用我们在第
11
章添加的
dismissModalView
方法。

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

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