????最近在做一個(gè)文檔管理的個(gè)人項(xiàng)目時(shí)碰到了一些關(guān)于這樣那樣的iOS文檔交互處理的問題,在這里做一個(gè)小結(jié)??
目錄:
- iOS中的文檔交互簡介
- 如何預(yù)覽和打開文檔
- 打通與其他app之間的文檔交互--注冊文件支持類型
- 打開從其他app傳過來的文檔
- Quick Look Framework的使用
- 小結(jié)
1.iOS中的文檔交互簡介
????iOS中為開發(fā)者提供了一種即便app并不支持某些文件,也可以打開預(yù)覽該文件的技術(shù)。
????iOS中還提供了一個(gè)關(guān)聯(lián)文件類型的系統(tǒng)注冊表,如果你的app注冊了相關(guān)文件的類型,那么系統(tǒng)會(huì)允許你的app可以處理從其他應(yīng)用程序中打開的文件;同時(shí)支持處理airDrop傳輸過來的文件。
?這些強(qiáng)大的技術(shù)包括 UIKit
中的UIDocumentInteractionController
和 Quick Look framework
框架。
2.如何預(yù)覽和打開文檔
????任何app都可以使用文檔交互控制器進(jìn)行文件操作。相關(guān)交互場景可能發(fā)生在需要從網(wǎng)絡(luò)下載文件進(jìn)而顯示預(yù)覽的app里。例如,電子郵件類型的app使用文檔交互控制器預(yù)覽或打開某一封郵件附件中的文件。
????除了預(yù)覽和打開某些文件的需求外,還有一些文件交互是發(fā)生在文件共享場景下的。例如,從其他app中通過系統(tǒng)分享或者airdrop分享某些特定類型的文件進(jìn)行處理。
使用UIDocumentInteractionController進(jìn)行文件交互
????初始化一個(gè)UIDocumentInteractionController
實(shí)例,并設(shè)置代理,由其代理方法可以獲知相關(guān)視圖的信息以及方便在與用戶交互時(shí)進(jìn)行一些額外的操作。簡單的初始化代碼如下:
?- (UIDocumentInteractionController *) setupControllerWithURL: (NSURL) fileURL
? usingDelegate: (id <UIDocumentInteractionControllerDelegate>) interactionDelegate {
? UIDocumentInteractionController *interactionController =
[UIDocumentInteractionController interactionControllerWithURL: fileURL];
? interactionController.delegate = interactionDelegate;
? return interactionController;
?}
????UIDocumentInteractionController
中提供了一些關(guān)于文件名、文件類型以及URL的屬性,可以方便開發(fā)者獲取文件相關(guān)信息。
UIDocumentInteractionController的兩種操作
????UIDocumentInteractionController
提供了兩種操作文件的方式,一種是文件預(yù)覽,效果圖如下所示:
????預(yù)覽和打開文件可以使用以下方法:
// Bypasses the menu and opens the full screen preview window for the item at URL. Returns NO if the item could not be previewed.
// Note that you must implement the delegate method documentInteractionControllerViewControllerForPreview: to preview the document.
- (BOOL)presentPreviewAnimated:(BOOL)animated;
????如果不需要打開文件只是進(jìn)行文件分享,則可以使用以下方法:
// This is the default method you should call to give your users the option to quick look, open, or copy the document.
// Presents a menu allowing the user to Quick Look, open, or copy the item specified by URL.
// This automatically determines the correct application or applications that can open the item at URL.
// Returns NO if the options menu contained no options and was not opened.
// Note that you must implement the delegate method documentInteractionControllerViewControllerForPreview: to get the Quick Look menu item.
- (BOOL)presentOptionsMenuFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated;
????效果圖如下:
?demo戳這里查看
3. 打通與其他app之間的文檔交互--注冊文件支持類型
????上面介紹了app內(nèi)打開和分享文件的使用,如果你的app支持打開某些特殊類型的文件,并允許其他app通過文件交互技術(shù)將文件交給你的app處理的話,你可以在系統(tǒng)注冊表中注冊相關(guān)文件支持類型。
????如果想要聲明對某些文件類型的支持,可以在Info.plist
中添加CFBundleDocumentTypes
鍵值對。系統(tǒng)會(huì)在注冊表中添加該信息,然后其他app就可以通過文檔交互控制器進(jìn)行訪問了。
????CFBundleDocumentTypes
的值是一個(gè)字典數(shù)組,數(shù)組中的每一個(gè)字典都包含了一個(gè)特定文檔類型的相關(guān)信息。
????正常情況下文檔的類型和這些特定的文件類型是一一對應(yīng)的,但是如果你的應(yīng)用程序處理的文件類型不止一個(gè),那么可以將這些文件類型組合在一起,作為單個(gè)文檔類型來處理。
????例如,如果你的本地文檔同時(shí)包含一個(gè)舊的文件格式和一個(gè)新的文件格式,比較典型的像.doc
和.docx
,那么就可以將它們組合在同一個(gè)文檔類型中。這樣,舊的文件格式和新的文件格式就會(huì)被當(dāng)成同一種文檔類型,并且使用相同的方式進(jìn)行處理。
CFBundleDocumentTypes
中每個(gè)字典都包括以下key:
?- CFBundleTypeName
--------------文件類型的名字
?- CFBundleTypeIconFiles
---------用于作文件icon的圖片名數(shù)組
?- LSItemContentTypes
------------當(dāng)前所支持的文件類型的UTI類型的字符串?dāng)?shù)組
?- LSHandlerRank
-----------------標(biāo)示當(dāng)前app對該文件類型的權(quán)限
????其中LSItemContentTypes
中的UTI
字符串是真正確定某個(gè)文件類型的唯一標(biāo)示。系統(tǒng)聲明的UTI可以點(diǎn)這里查看,非常多
????而LSHandlerRank
的權(quán)限共分為以下幾種:
?- Owner
--------------app為該文件類型的主要?jiǎng)?chuàng)建者和擁有者
?- Default
------------app為該文件類型的開啟者,如果沒有指定權(quán)限則默認(rèn)為Default
?- Alternate
----------app為該文件類型的二級(jí)查看器
?- None
---------------app不會(huì)被選擇打開這個(gè)類型的文件,但是它可以接受這種類型的文件
????接收的文件會(huì)被存儲(chǔ)在app的Document目錄的indox文件夾下。
????下面是一個(gè)pdf文件類型聲明的簡單示例:
<dict>
<key>CFBundleTypeName</key>
<string>PDF文件</string>
<key>CFBundleTypeIconFiles</key>
<array>
<string>MySmallIcon.png</string>
<string>MyLargeIcon.png</string>
</array>
<key>LSItemContentTypes</key>
<array>
<string>com.adobe.pdf</string>
</array>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
????當(dāng)app添加文件類型支持之后,用戶使用文檔交互控制器從其他app分享相關(guān)文件類型時(shí),就會(huì)發(fā)現(xiàn)自己的app在可操作列表里面了。如下圖:
?當(dāng)然如果用戶是通過airDrop進(jìn)行文件傳輸,app同樣會(huì)出現(xiàn)在可操作列表里面,如下圖:
4. 打開從其他app傳過來的文檔
????當(dāng)app添加相關(guān)文件類型支持之后,系統(tǒng)可能要求您的應(yīng)用程序打開一個(gè)特定的文件并將其呈現(xiàn)給用戶。那么app該如何監(jiān)聽傳過來的文件呢?
????這里分兩種情況,當(dāng)app處于未啟動(dòng)狀態(tài)時(shí),可以通過以下方法獲取相關(guān)信息:
application:willFinishLaunchingWithOptions:
或者
application:didFinishLaunchingWithOptions:
????而文件相關(guān)信息包含在上面?zhèn)z個(gè)方法的options
參數(shù)字典中,你可以通過查看options
字典中的以下key來獲取相關(guān)信息。
?- UIApplicationLaunchOptionsURLKey
------------------包含了該文件的NSURL對象
?- UIApplicationLaunchOptionsSourceApplicationKey
----包含了文件傳輸源app的bundleId
?- UIApplicationLaunchOptionsAnnotationKey
-----------包含了一個(gè)文件傳輸源app傳遞過來的關(guān)于該文件的屬性列表。
????而當(dāng)app處于啟動(dòng)狀態(tài)時(shí),則可以通過以下方法獲取到傳輸來的文檔相關(guān)信息。
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return true
}
小貼士:
????如果app只是支持預(yù)覽某些文件,而不必保存該文件,則可以在以上方法中獲取到文件存儲(chǔ)到本地的路徑,將其刪除。
5. Quick Look Framework的使用
????當(dāng)文件存儲(chǔ)到本地之后,為了獲得對文件預(yù)覽的更多控制,可以直接使用 Quick Look Framework
。
????該框架最主要的類是QLPreviewController
,QLPreviewController
提供了代理QLPreviewControllerDelegate
響應(yīng)用戶對文件的相關(guān)操作,并提供了一個(gè)數(shù)據(jù)源代理QLPreviewControllerDataSource
,設(shè)置預(yù)覽文件的相關(guān)源數(shù)據(jù)。
????QLPreviewController
可以使用UINavigationController
push出來,也可以使用模態(tài)的方式彈出。并且使用模態(tài)彈出的時(shí)候還會(huì)有更多操作手勢。
????QLPreviewController
支持以下文件格式的預(yù)覽:
?- 蘋果自家的iWork相關(guān)文檔(Pages、Numbers、Keynote)
?- Microsoft辦公文檔(office97以及之后的版本)
?- PDF文件
?- RTF文檔
?- 圖片
?- UTI標(biāo)示符和public.text
符合的文本文件
?- csv文件
????QLPreviewController
還支持同時(shí)預(yù)覽多個(gè)文件,支持多文件的左右切換,由其數(shù)據(jù)源控制。
6. 小結(jié)
????在筆者學(xué)習(xí)過程中也發(fā)現(xiàn)了一些關(guān)于UIDocumentInteractionController
和 Quick Look framework
這些用于進(jìn)程間通信的remote viewController的限制,比如nav
和toolbar
及其action的無法自定義。
????關(guān)于它們的自定義,筆者現(xiàn)在的做法是子類化UIDocumentInteractionController
和 Quick Look framework
,在控制器的生命周期方法中獲取其nav
和toolbar
,修改nav
和toolbar
的相關(guān)屬性以達(dá)到自定義的需求。
????除了以上提到的文檔交互相關(guān)內(nèi)容,蘋果還提供了
Document Provider Extensions,它允許其他app使用文檔選擇器來訪問文檔。
????相關(guān)的,開發(fā)者也可以在自己的app中集成iCloudKit
,進(jìn)一步加深用戶的文檔交互操作。(最新出的還有一個(gè)PDFKit,這幾個(gè)有時(shí)間筆者會(huì)補(bǔ)上???)