Intermediate iOS 11 Programming with Swift(十七): AirDrop, UIActivityViewController和统一类型标识符的使用

本文是Intermediate iOS 11 Programming with Swift 4系列 的 第 十七 篇.

17.0


AirDrop是苹果对文件和数据共享的回应。在iOS 7之前,用户必须依靠第三方应用程序(如Bump)在iOS设备之间共享文件。自iOS 7发布以来,iOS用户可以使用名为AirDrop的功能与附近的iOS设备共享数据。简而言之,该功能允许你分享照片、视频、联系人、url、存折、应用商店的应用列表、iTunes商店的媒体列表、地图中的位置等等.

如果你能把AirDrop整合到你的应用程序中,岂不是很棒?”您的用户可以轻松地与附近的设备共享照片、文本文件或任何其他类型的文档。iOS SDK中绑定的UIActivityViewController类使您可以轻松地将AirDrop嵌入到应用程序中。该类保护您不受文件共享的底层细节的影响。您所需要做的就是告诉类您想要共享的对象,控制器处理其余的对象。在这一章中,我们将演示UIActivityViewController的使用,以及如何使用它通过空投来共享图像和文档.

要激活AirDrop,只需打开控制中心并点击AirDrop。根据您希望与谁共享数据,您可以选择Contact Only或Everyone。如果您选择了联系人唯一选项,您的设备将只会被列出在联系人中的人发现。如果选择了Everyone选项,您的设备可以从任何其他设备中发现。

AirDrop使用蓝牙扫描附近的设备。当通过蓝牙建立连接时,它将创建一个特殊的Wi-Fi网络,将两个设备连接在一起,从而实现更快的数据传输。这并不意味着你需要将设备连接到Wi-Fi网络才能使用AirDrop;你的WiFi只要打开就可以进行数据传输。

例如,假设你想将照片应用程序中的一张照片从一个iPhone传到另一个iPhone。假设您已经在两个设备上启用了AirDrop,那么您可以通过点击屏幕左下角的share按钮(带有向上箭头的按钮)与另一个设备共享照片。

在AirDrop区,您应该看到有资格共享的设备的名称。当屏幕关闭时,AirDrop是不可用的,所以请确保接收端设备打开。然后,您可以选择要与之共享照片的设备。在接收设备上,您应该看到照片的预览和确认请求。接收方可以接受或拒绝接收图像。如果他们选择了accept选项,照片就会被传送并自动保存在相机胶卷中.


17.1 在iPhone 上使用AirDrop


AirDrop不仅适用于照片应用程序,你还可以在联系人、iTunes、应用商店和Safari浏览器中分享物品,举几个例子。如果你是AirDrop新手,你现在应该对AirDrop的工作原理有了更好的了解。

让我们看看如何将AirDrop集成到一个应用程序中,以共享各种类型的数据.

UIActivityViewController 概述

你可能会认为实现AirDrop功能需要很多行代码。相反,只需要几行代码就可以嵌入AirDrop。UIKit框架提供的UIActivityViewController类简化了集成过程。

UIActivityViewController类是一个标准的视图控制器,它提供了一些标准的服务,例如将项目复制到剪贴板、将内容共享到社交媒体站点、通过消息发送项目等。在iOS 8或更高版本中,activity view controller进一步增加了对app扩展的支持.

这个类很容易使用。假设您有一个使用AirDrop共享的对象数组。你需要做的就是用对象数组创建UIActivityViewController的一个实例,然后在屏幕上显示控制器.

```

let  objectsToShare = [fileURL]

let activityController = UIActivityController(activityItems: objectsToShare, applicationActivities: nil) present(activityController, animated: true, completion: nil)

```

如您所见,只需几行代码,您就可以使用AirDrop选项打开一个活动视图。当检测到附近的设备时,如果选择共享数据,活动控制器将自动显示该设备并处理数据传输。默认情况下,活动控制器包括消息、Flickr和新浪微博等共享选项。或者,您可以通过设置控制器的exclude activitytypes属性来排除这些类型的活动. 

下面是简单的代码示例:

```

let excludedActivities = [UIActivityType.postToWeibo, UIActivityType.message,  UIActivityType.postToTencentWeibo]

activityController.excludeActiviTypes =  excludedActivities

```

您可以使用UIActivityViewController来共享不同类型的数据,包括字符串、UIImage和URL。您不仅可以使用URL共享链接,而且还允许开发人员通过使用文件URL传输任何类型的文件。当另一台设备接收到数据时,它会根据数据类型自动打开app。所以,如果一个UIImage对象被传输,接收到的图像会显示在Photos app中。当你传输一个PDF文件时,另一个设备会在Safari中打开它。如果你只是共享一个字符串对象,数据就会显示在Notes应用程序中.

当另一台设备接收到数据时,它会根据数据类型自动打开app。所以,如果一个UIImage对象被传输,接收到的图像会显示在Photos app中。当你传输一个PDF文件时,另一个设备会在Safari中打开它。如果你只是共享一个字符串对象,数据就会显示在Notes应用程序中. 


Demo App

为了让你更好地理解UIActivityViewController和AirDrop,我们将像往常一样构建一个演示应用。同样,这个应用程序非常简单。启动后,您将看到一个表视图,其中列出了一些文件,包括图像文件、PDF文件、文档和Powerpoint。您可以单击文件并在detail视图中查看其内容。在content视图中,在屏幕底部有一个工具栏。点击工具栏上的分享操作按钮,会弹出AirDrop选项,可以与附近的设备分享文件.

这里下载简单的代码.

17.2 Demo App


项目模板已经包含storyboard和自定义类。表视图控制器与AirDropTableViewController关联,而细节视图控制器与DetailViewController关联。DetailViewController对象简单地使用WKWebView来显示文件内容。我们要做的是在细节视图中添加一个共享按钮来激活AirDrop.

添加Share Button

首先,让我们去storyBoard。将工具栏从对象库拖动到详细视图控制器,并将其放置在控制器的底部。选择默认的bar按钮项,并在属性检查器中将其标识符更改为Action.


17.3 在detail View Controller 添加 toolBar

接下来. 给toolBar 添加约束 .否则,它将无法在某些设备上正常显示。现在,选择工具栏。在自动布局栏中,单击Add new constraints按钮来添加一些间距约束。设置左、右和底部的间距值为0。单击Add 3 Constraints来添加空间约束。


17.4 加 约束

新添加的约束确保工具栏始终显示在视图控制器的底部。回到DetailViewController。为共享操作添加一个动作方法:

@IBAction func share (sender: AnyObject) {

  }

回到 Main.storyboard 连接 Share Button 方法

17.5


 AirDrop 实现文件共享

现在已经完成了UI 方面的准备, 接着要完成代码部分. 在DetailController类里面补全 Share 方法.

@IBAction func share(sender: AnyObject) {

    if let fileURL = fileToURL(file: filename) {

        let objectsToShare = [fileURL]

        let activityController = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

        let excludedActivities = [UIActivityType.postToFlickr, UIActivityType.postToWeibo, UIActivityType.message, UIActivityType.mail, UIActivityType.print, UIActivityType.copyToPasteboard, UIActivityType.assignToContact, UIActivityType.saveToCameraRoll, UIActivityType.addToReadingList, UIActivityType.postToFlickr, UIActivityType.postToVimeo, UIActivityType.postToTencentWeibo]

        activityController.excludedActivityTypes = excludedActivities

        present(activityController, animated: true, completion: nil)

   }

}

代码都很简单, 这里不翻译了.

DetailViewController的filename属性包含要共享的文件名。在将文件传递给活动视图控制器之前,我们需要首先找到文件的完整路径。在项目模板中,我已经为此目的包含了一个helper方法

 func fileToURL(file: String) -> URL? {

    // Get the full path of the file

    let fileComponents = file.components(separatedBy: ".")

    if let filePath = Bundle.main.path(forResource: fileComponents[0], ofType: fileComponents[1]) {

        return URL(fileURLWithPath: filePath)

    }

    return nil

}

这个代码也很简单, 例如, 这个image 文件 glico.jpg , 得到的完整路径如下: 

file:///Users/simon/Library/Developer/CoreSimulator/Devices/7DC35502-54FD-447B-B10F-2B7B0FD5BDDF/data/Containers/Bundle/Application/01827504-4247-4C81-9DE5-02BEAE94C7E5/AirDropDemo.app/glico.jpg

文件URL根据您正在运行的设备而异。但是URL应该以文件:// protocol开始。通过文件URL对象,我们创建了相应的数组并将其传递给UIActivityViewController进行AirDrop共享.


创建一个 AirDrop Demo

这就是实现AirDrop所需要的全部。现在可以测试应用程序了。编译并在真机上运行它。当然,你需要一个真正的设备来测试AirDrop  共享特性在模拟器中无法工作

此外,你需要至少两台iOS设备或一台Mac电脑来测试共享功能


17.6 真机测试


第一次运行, 选择文件, 确保两台设备都支持AirDrop

iPad 

如果你在iPad 上运行 会报错:  

2017-11-14 12:26:32.284152+0800 AirDropDemo[28474:5821534] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIActivityViewController (<UIActivityViewController: 0x7f9d4985d400>). In its current trait environment, the modalPresentationStyle of a UIActivityViewController with this style is UIModalPresentationPopover. You must provide location information for this popover through the view controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the view controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.

在iPad上,UIActivityViewController显示为弹窗而不是动作表单。在这种情况下,您必须为弹出式表示控制器指定源视图或源栏按钮项。对于我们的演示应用程序,当用户单击Share按钮时,我们希望从按钮中显示弹出窗口。为此,在DetailViewController中为Share按钮创建一个outlet变量。在接口生成器中快速建立连接:

@IBOutlet  var actionButton : UIBarButtonItem !

接下来,  回到 DetailViewController.swift , 在调用share(sender:)方法的present(activityController, animated: true, completion: nil)之前插入以下代码 :

if let popOverController = activityController.popoverPresentationController {

    popOverController.barButtonItem = actionButtonItem

}

当一个设备(例如iPad)使用弹窗来显示UIActivityViewController时,popoverPresentationController属性有一个值。因此,我们测试属性是否包含值,然后将其barButtonItem属性设置为Share按钮。 如果你在iPad上运行这个演示程序,你会得到这样的结果:


17.7 iPad  上的 分享



类型标识符

当你与另一个iOS设备分享图片时,接收端会自动打开图片应用并保存图片。如果您传输PDF或文档文件,接收设备可能会提示您选择一个应用程序打开该文件,或者直接在iBooks中打开它。iOS如何知道特定数据类型使用哪个应用程序?

UTIs(统一类型标识符的缩写)是苹果在系统中标识数据的答案。简而言之,统一类型标识符是特定类型数据或文件的唯一标识符。例如,com.adobe。pdf表示pdf文档和公共文档。png表示一个png图像。详细文档点击 ---> 苹果 UTIs.   一个能够打开特定类型文件的应用程序将被注册到iOS中处理该UTI。因此,每当打开这类文件时,iOS就会将该文件交给特定的应用程序. 

17.8 


该系统允许多个应用程序注册同一个UTI。在这种情况下,iOS会提示用户打开文件所需的应用程序列表。例如,当您共享一个文档时,接收设备将提示一个菜单供用户选择.


总结

AirDrop是一个非常方便的功能,它提供了一种在设备之间共享数据的好方法。最棒的是,内置的UIActivityViewController让开发者很容易在他们的应用程序中添加AirDrop支持。正如用Demo看到的,您只需要几行代码就可以实现该特性. 

    欢迎下载原项目

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    爱运动爱学习阅读 15,037评论 3 114
  • 想给你说晚安 又怕过了今天,没了明天 你迟疑的态度 我一直不断的纠缠 让你对我淡了、厌了 你说再见吧 我却迟迟不肯...
    酥白阅读 131评论 -1 1
  • 每一个孩子,都是从懵懂无知的状态中呱呱落地,继而去适应这个既定世界的规则和边界,在这个过程中,每一次试错都是矫正自...
    爱与我为邻阅读 96评论 0 1
  • 030:年龄与疾病 总时间限制: 1000ms 内存限制: 65536kB描述某医院想统计一下某项疾病的获得与否与...
    Lyn谷神不死阅读 859评论 0 1
  • 1. 年少想仗剑走天涯 看遍世间繁华落败 篡改所有灰色结界 江湖会因我而不同 跌跌撞撞成长 酸酸涩涩承受 零零落落...
    买只荔枝阅读 457评论 9 12
  • 根据股票初级课程LIP师兄所课, 利用查询股票工具-理杏仁,分别搜索古井贡酒,及海康威视的利润表查询营业收入,以及...
    老李言商阅读 435评论 2 4