本文是Intermediate iOS 11 Programming with Swift 4系列?的 第 十七 篇.
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選項蹈丸,照片就會被傳送并自動保存在相機膠卷中.
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è)備分享文件.
在這里下載簡單的代碼.
項目模板已經(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.
接下來. 給toolBar 添加約束 .否則,它將無法在某些設(shè)備上正常顯示∮Ш悖現(xiàn)在谴咸,選擇工具欄。在自動布局欄中骗露,單擊Add new constraints按鈕來添加一些間距約束岭佳。設(shè)置左、右和底部的間距值為0萧锉。單擊Add 3 Constraints來添加空間約束珊随。
新添加的約束確保工具欄始終顯示在視圖控制器的底部∈料叮回到DetailViewController叶洞。為共享操作添加一個動作方法:
@IBAction func share (sender: AnyObject) {
? }
回到 Main.storyboard 連接 Share Button 方法
?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電腦來測試共享功能
第一次運行, 選擇文件, 確保兩臺設(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é)果:
類型標識符
當你與另一個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)用程序.?
該系統(tǒng)允許多個應(yīng)用程序注冊同一個UTI壳坪。在這種情況下舶得,iOS會提示用戶打開文件所需的應(yīng)用程序列表。例如弥虐,當您共享一個文檔時扩灯,接收設(shè)備將提示一個菜單供用戶選擇.
總結(jié)
AirDrop是一個非常方便的功能,它提供了一種在設(shè)備之間共享數(shù)據(jù)的好方法霜瘪。最棒的是,內(nèi)置的UIActivityViewController讓開發(fā)者很容易在他們的應(yīng)用程序中添加AirDrop支持惧磺。正如用Demo看到的颖对,您只需要幾行代碼就可以實現(xiàn)該特性.?