天天看點

UIActivityViewController

釋出于:2014-04-25 09:51閱讀數:9045

特定的程式設計語言,如 Lisp、lo 和 Mathematica 都是同像性的(homoiconic),意味着它們的代碼可作為資料原語呈現,也就是說它們自身就可在代碼中被操縱。許多其他語言,包括 Objective-C ,就不同了

“”

閱讀器

UIActivityViewController

本文由@nixzhu翻譯至nshipster的《UIActivityViewController》

資料與代碼的關系一直都讓人好奇。

特定的程式設計語言,如 Lisp、lo 和 Mathematica 都是同像性的(homoiconic),意味着它們的代碼可作為資料原語呈現,也就是說它們自身就可在代碼中被操縱。許多其他語言,包括 Objective-C ,就不同了,在兩者之間建立了嚴格的界限,回避 eval() 和其它潛在的危險的動态訓示加載方法。

當問題中的資料過大或難以表示為除了位元組流之外的任何東西時,那麼代碼與資料的這種緊張關系就達到了一個新的高度。關于“如何編碼、解碼以及解釋圖像、文檔和媒體的二進制表示”的問題從最開始的作業系統開始就一直存在着。

OS X 的 Core Services 架構與 iOS 的移動 Core Services 架構都提供函數通過通用類型辨別符(Universal Type Identifiers,即UTI)來根據檔案擴充和MIME類型識别和分類資料類型。UTI提供了可擴充和可繼承的分類系統,它能給予開發人員極大的靈活性,即使是處理最奇特的檔案類型。例如,一個 Ruby 源代碼檔案(.rb)被分類為 Ruby 源代碼 > 源代碼 > 文本 > 内容 > 資料;一個 QuickTime 電影檔案(.mov)被分類為視訊 > 電影 > 試聽内容 > 内容 > 資料;

在桌面檔案系統抽象裡,UTI工作得相當好。然而,在一個移動範式裡,檔案和目錄對于使用者來說都被隐藏了,于是這很快就失效了。而且,更重要的是,雲服務和社交媒體的興起已經讓遠端實體比本地檔案具有更重要的地位。是以,UTI和URL之間出現了緊張關系。

很明顯我們需要其它的某種東西。那 UIActivityViewController 能成為我們拼命追求的解決辦法嗎?

UIActivityViewController ,出現于 iOS 6,在應用裡為分享和操作資料提供了一個統一的服務接口。

給出一個可操作資料的集合,那一個 UIActivityViewController 執行個體就可如下建立:

這将在螢幕的底部呈現如下所示的東西: 

UIActivityViewController

預設情況下,UIActivityViewController 将顯示所有可用于所提供内容的服務,但我們也可以排除特定的 Activity 類型。

Activity 類型又分為“操作”和“分享”兩大類:

UIActivityCategoryAction

1. UIActivityTypePrint

2. UIActivityTypeCopyToPasteboard

3. UIActivityTypeAssignToContact

4. UIActivityTypeSaveToCameraRoll

5. UIActivityTypeAddToReadingList

6. UIActivityTypeAirDrop

UIActivityCategoryShare

1. UIActivityTypeMessage

2. UIActivityTypeMail

3. UIActivityTypePostToFacebook

4. UIActivityTypePostToTwitter

5. UIActivityTypePostToFlickr

6. UIActivityTypePostToVimeo

7. UIActivityTypePostToTencentWeibo

8. UIActivityTypePostToWeibo

每個 Activity 類型都支援好多種不同的資料類型。例如,一條 Tweet 可能由 NSString 以及一個附加的圖像 和/或 URL 所組成。

不同的 Activity 類型所支援的資料類型 

UIActivityViewController
UIActivityViewController

<UIActivityItemSource> & UIActivityProvider

類似于一個剪貼闆條目隻在必要時才提供資料,為了避免過多的記憶體配置設定或處理時間, Activity 條目可以是自定義類型。

<UIActivityItemSource>

擷取資料項

1. activityViewControllerPlaceholderItem:

2. activityViewController:itemForActivityType:

提供資料項資訊

1. activityViewController:subjectForActivityType:

2. activityViewController:dataTypeIdentifierForActivityType:

3. activityViewController:thumbnailImageForActivityType:suggestedSize:

一個關于這些方法如何使用的例子是自定義一個消息,其根據是否要分享到 Facebook 或 Twitter 分别定義。

建立一個自定義 UIActivity

除了上述系統提供的 Activity ,你也可以自己建立 Activity。

作為例子,讓我們建立一個自定義 Activity 類型,它能接受一個圖檔 URL 并使用 mustache.me 為其安上一瞥胡子。 

UIActivityViewController

之前

UIActivityViewController

之後

首先,我們為 Activity 類型定義一個反向DNS辨別符(reverse-DNS identifier),指定類别為 UIActivityCategoryAction ,然後提供一個本地化的标題和一個合适于iOS版本的圖像:

接下來,我們建立一個幫助函數,HIPMatchingURLsInActivityItems,它傳回一個由任何所支援類型的圖像 URL 組成的數組。

這個函數用于 -canPerformWithActivityItems: 和 prepareWithActivityItems: 以取得第一個 PNG 或 JPEG 的加了胡子的圖像 URL,如果有的話。

我們的網絡服務提供了好幾種胡子選項,它們定義在一個 NS_ENUM 中:

最終,我們提供一個 UIViewController 來顯示圖像。在這個例子裡,一個簡單的 UIWebView 控制器就夠了。 

要使用我們全新的胡子 Activity,我們簡單地将其傳遞給一個 UIActivityViewController 的初始化函數即可:

手動調用操作

現在正是回憶起 “UIActivityViewController 允許使用者執行它們選擇的操作” 的好時機,但當情況需要時,分享依然可以手動調用。

為了完整性,下面就來介紹手動執行這些操作的步驟: 

打開 URL

系統支援的 URL scheme 包括:mailto://、tel://、sms://、and maps://。

添加到 Safari 閱讀清單

儲存到相冊

發送短信

發送郵件

發送推文

IntentKit

雖然所有這些都讓人影響深刻也很有用,但在與 Android 上的豐富的 Intent 模型對比之下,iOS 的 Activity 範式中還是有一些特殊的缺失。

在 Android 上,應用可以注冊不同的 Intent,以表面它們可用于地圖或作為浏覽器,而且能被選擇為相關 Activity 的預設應用,例如導航或将某個URL加入書簽。

雖然 iOS 缺少可擴充的基礎架構來支援這些,但一個第三方的庫,叫做 IntentKit,由 @lazerwalker (有着 f*ingblocksyntax.com 的聲譽) 編寫,它是一個有趣的關于我們如何縮小差距的例子。 

UIActivityViewController

正常情況下,在一開始一個開發者就要做許多工作,例如查詢某個特定的應用是否已被安裝,以及構造一個 URL 以支援某個特定的 Activity 等。

IntentKit 合并了連接配接到這些最流行的服務(如 Web、地圖、郵件、Twitter、Facebook以及Google+這些用戶端)的邏輯,而且它的 UI 非常類似 UIActivityViewController。

任何想将其應用的分享體驗提高一個層次的人都應該研究一下它。

還有一個要發出的有力争論是,關于 iOS 平台的長期生存能力取決于如 UIActivityViewController 這樣的分享機制。俗話說,“資訊需要自由”。而任何阻擋人民聯盟的事物終将輸給那些不阻擋聯盟的事物。

公開的 遠端視圖控制器(remote view controller) API 的未來前景給了我關于iOS上分享的未來希望。雖然對現在來說,我們當然可以做得比 UIActivityViewController 更差。(譯者注:是這個意思嗎? For now, though, we could certainly do much worse than UIActivityViewController.)