Intermediate iOS 11 Programming with Swift(十七): AirDrop, UIActivityViewController和統(tǒng)一類型標識符的使用

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

17.0


AirDrop是蘋果對文件和數(shù)據(jù)共享的回應(yīng)。在iOS 7之前,用戶必須依靠第三方應(yīng)用程序(如Bump)在iOS設(shè)備之間共享文件搂鲫。自iOS 7發(fā)布以來褂萧,iOS用戶可以使用名為AirDrop的功能與附近的iOS設(shè)備共享數(shù)據(jù)。簡而言之淑际,該功能允許你分享照片辛燥、視頻、聯(lián)系人迈窟、url私植、存折、應(yīng)用商店的應(yīng)用列表车酣、iTunes商店的媒體列表曲稼、地圖中的位置等等.

如果你能把AirDrop整合到你的應(yīng)用程序中,豈不是很棒?”您的用戶可以輕松地與附近的設(shè)備共享照片骇径、文本文件或任何其他類型的文檔躯肌。iOS SDK中綁定的UIActivityViewController類使您可以輕松地將AirDrop嵌入到應(yīng)用程序中者春。該類保護您不受文件共享的底層細節(jié)的影響破衔。您所需要做的就是告訴類您想要共享的對象,控制器處理其余的對象钱烟。在這一章中晰筛,我們將演示UIActivityViewController的使用,以及如何使用它通過空投來共享圖像和文檔.

要激活A(yù)irDrop拴袭,只需打開控制中心并點擊AirDrop读第。根據(jù)您希望與誰共享數(shù)據(jù),您可以選擇Contact Only或Everyone拥刻。如果您選擇了聯(lián)系人唯一選項怜瞒,您的設(shè)備將只會被列出在聯(lián)系人中的人發(fā)現(xiàn)。如果選擇了Everyone選項般哼,您的設(shè)備可以從任何其他設(shè)備中發(fā)現(xiàn)吴汪。

AirDrop使用藍牙掃描附近的設(shè)備。當通過藍牙建立連接時蒸眠,它將創(chuàng)建一個特殊的Wi-Fi網(wǎng)絡(luò)漾橙,將兩個設(shè)備連接在一起,從而實現(xiàn)更快的數(shù)據(jù)傳輸楞卡。這并不意味著你需要將設(shè)備連接到Wi-Fi網(wǎng)絡(luò)才能使用AirDrop;你的WiFi只要打開就可以進行數(shù)據(jù)傳輸霜运。

例如,假設(shè)你想將照片應(yīng)用程序中的一張照片從一個iPhone傳到另一個iPhone蒋腮。假設(shè)您已經(jīng)在兩個設(shè)備上啟用了AirDrop淘捡,那么您可以通過點擊屏幕左下角的share按鈕(帶有向上箭頭的按鈕)與另一個設(shè)備共享照片。

在AirDrop區(qū)池摧,您應(yīng)該看到有資格共享的設(shè)備的名稱焦除。當屏幕關(guān)閉時,AirDrop是不可用的险绘,所以請確保接收端設(shè)備打開踢京。然后誉碴,您可以選擇要與之共享照片的設(shè)備。在接收設(shè)備上瓣距,您應(yīng)該看到照片的預(yù)覽和確認請求黔帕。接收方可以接受或拒絕接收圖像。如果他們選擇了accept選項蹈丸,照片就會被傳送并自動保存在相機膠卷中.


17.1 在iPhone 上使用AirDrop


AirDrop不僅適用于照片應(yīng)用程序成黄,你還可以在聯(lián)系人、iTunes逻杖、應(yīng)用商店和Safari瀏覽器中分享物品乳蛾,舉幾個例子。如果你是AirDrop新手宾巍,你現(xiàn)在應(yīng)該對AirDrop的工作原理有了更好的了解剩拢。

讓我們看看如何將AirDrop集成到一個應(yīng)用程序中,以共享各種類型的數(shù)據(jù).

UIActivityViewController 概述

你可能會認為實現(xiàn)AirDrop功能需要很多行代碼够话。相反蓝翰,只需要幾行代碼就可以嵌入AirDrop。UIKit框架提供的UIActivityViewController類簡化了集成過程女嘲。

UIActivityViewController類是一個標準的視圖控制器畜份,它提供了一些標準的服務(wù),例如將項目復(fù)制到剪貼板欣尼、將內(nèi)容共享到社交媒體站點爆雹、通過消息發(fā)送項目等。在iOS 8或更高版本中愕鼓,activity view controller進一步增加了對app擴展的支持.

這個類很容易使用钙态。假設(shè)您有一個使用AirDrop共享的對象數(shù)組。你需要做的就是用對象數(shù)組創(chuàng)建UIActivityViewController的一個實例拒啰,然后在屏幕上顯示控制器.

```

let ?objectsToShare = [fileURL]

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

```

如您所見驯绎,只需幾行代碼,您就可以使用AirDrop選項打開一個活動視圖谋旦。當檢測到附近的設(shè)備時剩失,如果選擇共享數(shù)據(jù),活動控制器將自動顯示該設(shè)備并處理數(shù)據(jù)傳輸册着。默認情況下拴孤,活動控制器包括消息、Flickr和新浪微博等共享選項甲捏⊙菔欤或者,您可以通過設(shè)置控制器的exclude activitytypes屬性來排除這些類型的活動.?

下面是簡單的代碼示例:

```

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

activityController.excludeActiviTypes = ?excludedActivities

```

您可以使用UIActivityViewController來共享不同類型的數(shù)據(jù),包括字符串芒粹、UIImage和URL兄纺。您不僅可以使用URL共享鏈接,而且還允許開發(fā)人員通過使用文件URL傳輸任何類型的文件化漆。當另一臺設(shè)備接收到數(shù)據(jù)時估脆,它會根據(jù)數(shù)據(jù)類型自動打開app。所以座云,如果一個UIImage對象被傳輸疙赠,接收到的圖像會顯示在Photos app中。當你傳輸一個PDF文件時朦拖,另一個設(shè)備會在Safari中打開它圃阳。如果你只是共享一個字符串對象,數(shù)據(jù)就會顯示在Notes應(yīng)用程序中.

當另一臺設(shè)備接收到數(shù)據(jù)時璧帝,它會根據(jù)數(shù)據(jù)類型自動打開app捍岳。所以,如果一個UIImage對象被傳輸裸弦,接收到的圖像會顯示在Photos app中祟同。當你傳輸一個PDF文件時,另一個設(shè)備會在Safari中打開它理疙。如果你只是共享一個字符串對象,數(shù)據(jù)就會顯示在Notes應(yīng)用程序中.?


Demo App

為了讓你更好地理解UIActivityViewController和AirDrop泞坦,我們將像往常一樣構(gòu)建一個演示應(yīng)用窖贤。同樣,這個應(yīng)用程序非常簡單贰锁。啟動后赃梧,您將看到一個表視圖,其中列出了一些文件豌熄,包括圖像文件授嘀、PDF文件、文檔和Powerpoint锣险。您可以單擊文件并在detail視圖中查看其內(nèi)容蹄皱。在content視圖中,在屏幕底部有一個工具欄芯肤。點擊工具欄上的分享操作按鈕巷折,會彈出AirDrop選項,可以與附近的設(shè)備分享文件.

這里下載簡單的代碼.

17.2 Demo App


項目模板已經(jīng)包含storyboard和自定義類崖咨。表視圖控制器與AirDropTableViewController關(guān)聯(lián)锻拘,而細節(jié)視圖控制器與DetailViewController關(guān)聯(lián)。DetailViewController對象簡單地使用WKWebView來顯示文件內(nèi)容击蹲。我們要做的是在細節(jié)視圖中添加一個共享按鈕來激活A(yù)irDrop.

添加Share Button

首先署拟,讓我們?nèi)toryBoard婉宰。將工具欄從對象庫拖動到詳細視圖控制器,并將其放置在控制器的底部推穷。選擇默認的bar按鈕項芍阎,并在屬性檢查器中將其標識符更改為Action.


17.3 在detail View Controller 添加 toolBar

接下來. 給toolBar 添加約束 .否則,它將無法在某些設(shè)備上正常顯示∮Ш悖現(xiàn)在谴咸,選擇工具欄。在自動布局欄中骗露,單擊Add new constraints按鈕來添加一些間距約束岭佳。設(shè)置左、右和底部的間距值為0萧锉。單擊Add 3 Constraints來添加空間約束珊随。


17.4 加 約束

新添加的約束確保工具欄始終顯示在視圖控制器的底部∈料叮回到DetailViewController叶洞。為共享操作添加一個動作方法:

@IBAction func share (sender: AnyObject) {

? }

回到 Main.storyboard 連接 Share Button 方法

17.5


?AirDrop?實現(xiàn)文件共享

現(xiàn)在已經(jīng)完成了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屬性包含要共享的文件名。在將文件傳遞給活動視圖控制器之前禀崖,我們需要首先找到文件的完整路徑衩辟。在項目模板中,我已經(jīng)為此目的包含了一個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根據(jù)您正在運行的設(shè)備而異波附。但是URL應(yīng)該以文件:// protocol開始艺晴。通過文件URL對象,我們創(chuàng)建了相應(yīng)的數(shù)組并將其傳遞給UIActivityViewController進行AirDrop共享.


創(chuàng)建一個 AirDrop Demo

這就是實現(xiàn)AirDrop所需要的全部〉牛現(xiàn)在可以測試應(yīng)用程序了封寞。編譯并在真機上運行它。當然仅财,你需要一個真正的設(shè)備來測試AirDrop ?共享特性在模擬器中無法工作

此外狈究,你需要至少兩臺iOS設(shè)備或一臺Mac電腦來測試共享功能


17.6 真機測試


第一次運行, 選擇文件, 確保兩臺設(shè)備都支持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顯示為彈窗而不是動作表單盏求。在這種情況下抖锥,您必須為彈出式表示控制器指定源視圖或源欄按鈕項。對于我們的演示應(yīng)用程序风喇,當用戶單擊Share按鈕時宁改,我們希望從按鈕中顯示彈出窗口。為此魂莫,在DetailViewController中為Share按鈕創(chuàng)建一個outlet變量还蹲。在接口生成器中快速建立連接:

@IBOutlet ?var actionButton : UIBarButtonItem !

接下來, ?回到 DetailViewController.swift ,?在調(diào)用share(sender:)方法的present(activityController, animated: true, completion: nil)之前插入以下代碼 :

if let popOverController = activityController.popoverPresentationController {

? ? popOverController.barButtonItem = actionButtonItem

}

當一個設(shè)備(例如iPad)使用彈窗來顯示UIActivityViewController時,popoverPresentationController屬性有一個值。因此谜喊,我們測試屬性是否包含值潭兽,然后將其barButtonItem屬性設(shè)置為Share按鈕。?如果你在iPad上運行這個演示程序斗遏,你會得到這樣的結(jié)果:


17.7 iPad ?上的 分享



類型標識符

當你與另一個iOS設(shè)備分享圖片時山卦,接收端會自動打開圖片應(yīng)用并保存圖片。如果您傳輸PDF或文檔文件诵次,接收設(shè)備可能會提示您選擇一個應(yīng)用程序打開該文件账蓉,或者直接在iBooks中打開它。iOS如何知道特定數(shù)據(jù)類型使用哪個應(yīng)用程序?

UTIs(統(tǒng)一類型標識符的縮寫)是蘋果在系統(tǒng)中標識數(shù)據(jù)的答案逾一。簡而言之铸本,統(tǒng)一類型標識符是特定類型數(shù)據(jù)或文件的唯一標識符。例如,com.adobe遵堵。pdf表示pdf文檔和公共文檔箱玷。png表示一個png圖像。詳細文檔點擊 --->?蘋果 UTIs. ??一個能夠打開特定類型文件的應(yīng)用程序?qū)⒈蛔缘絠OS中處理該UTI陌宿。因此锡足,每當打開這類文件時,iOS就會將該文件交給特定的應(yīng)用程序.?

17.8?


該系統(tǒng)允許多個應(yīng)用程序注冊同一個UTI壳坪。在這種情況下舶得,iOS會提示用戶打開文件所需的應(yīng)用程序列表。例如弥虐,當您共享一個文檔時扩灯,接收設(shè)備將提示一個菜單供用戶選擇.


總結(jié)

AirDrop是一個非常方便的功能,它提供了一種在設(shè)備之間共享數(shù)據(jù)的好方法霜瘪。最棒的是,內(nèi)置的UIActivityViewController讓開發(fā)者很容易在他們的應(yīng)用程序中添加AirDrop支持惧磺。正如用Demo看到的颖对,您只需要幾行代碼就可以實現(xiàn)該特性.?

? ??歡迎下載原項目

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市磨隘,隨后出現(xiàn)的幾起案子缤底,更是在濱河造成了極大的恐慌,老刑警劉巖番捂,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件个唧,死亡現(xiàn)場離奇詭異,居然都是意外死亡设预,警方通過查閱死者的電腦和手機徙歼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人魄梯,你說我怎么就攤上這事桨螺。” “怎么了酿秸?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵灭翔,是天一觀的道長。 經(jīng)常有香客問我辣苏,道長肝箱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任稀蟋,我火速辦了婚禮煌张,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘糊治。我一直安慰自己唱矛,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布井辜。 她就那樣靜靜地躺著绎谦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粥脚。 梳的紋絲不亂的頭發(fā)上窃肠,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音刷允,去河邊找鬼冤留。 笑死,一個胖子當著我的面吹牛树灶,可吹牛的內(nèi)容都是我干的纤怒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼天通,長吁一口氣:“原來是場噩夢啊……” “哼泊窘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起像寒,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烘豹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后诺祸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體携悯,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年筷笨,在試婚紗的時候發(fā)現(xiàn)自己被綠了憔鬼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龟劲。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖逊彭,靈堂內(nèi)的尸體忽然破棺而出咸灿,到底是詐尸還是另有隱情,我是刑警寧澤侮叮,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布避矢,位于F島的核電站,受9級特大地震影響囊榜,放射性物質(zhì)發(fā)生泄漏审胸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一卸勺、第九天 我趴在偏房一處隱蔽的房頂上張望砂沛。 院中可真熱鬧,春花似錦曙求、人聲如沸碍庵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽静浴。三九已至,卻和暖如春挤渐,著一層夾襖步出監(jiān)牢的瞬間苹享,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工浴麻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留得问,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓软免,卻偏偏與公主長得像宫纬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子膏萧,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1哪怔、通過CocoaPods安裝項目名稱項目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,982評論 3 119
  • 想給你說晚安 又怕過了今天,沒了明天 你遲疑的態(tài)度 我一直不斷的糾纏 讓你對我淡了胚委、厭了 你說再見吧 我卻遲遲不肯...
    酥白閱讀 212評論 -1 1
  • 每一個孩子挟鸠,都是從懵懂無知的狀態(tài)中呱呱落地,繼而去適應(yīng)這個既定世界的規(guī)則和邊界亩冬,在這個過程中艘希,每一次試錯都是矯正自...
    愛與我為鄰閱讀 210評論 0 1
  • 030:年齡與疾病 總時間限制: 1000ms 內(nèi)存限制: 65536kB描述某醫(yī)院想統(tǒng)計一下某項疾病的獲得與否與...
    Lyn谷神不死閱讀 1,339評論 0 1
  • 1. 年少想仗劍走天涯 看遍世間繁華落敗 篡改所有灰色結(jié)界 江湖會因我而不同 跌跌撞撞成長 酸酸澀澀承受 零零落落...
    買只荔枝閱讀 664評論 9 12