iOS中的沙盒可以讓平臺(tái)更加的安全,這也是沙盒給用戶帶來(lái)的最主要好處。不過(guò)由于沙盒的嚴(yán)格限制,導(dǎo)致程序之間共享數(shù)據(jù)比較麻煩。一般在程序間共享文檔可以通過(guò)UIDocumentInteractionController類實(shí)現(xiàn)通訊。它支持在你的app中用其他app預(yù)覽和顯示文檔。同時(shí)也支持文件關(guān)聯(lián),允許其他app通過(guò)你的程序打開(kāi)文件。這些技術(shù)包括了UIKit中提供的UIDocumentInteractionController類(UIDocumentInteractionController Class Reference),以及Quick Look框架(Quick Look Framework Reference)。
本文將就如何在應(yīng)用之間進(jìn)行文件共享進(jìn)行基本探究。還請(qǐng)大牛勿噴。
效果圖

文件共享

跨APP傳文件
預(yù)覽文檔和呈現(xiàn)選項(xiàng)菜單
如果你的app需要打開(kāi)它不支持的文件(PDF文件、圖像文件,等等),或者需要將app的文件傳輸給另外一個(gè)允許接收此類型文件的app時(shí)??梢允褂梦募换タ刂破?UIDocumentInteractionController類的實(shí)例)為用戶提供可接收程序來(lái)處理文件,說(shuō)的簡(jiǎn)單點(diǎn)就是通過(guò)Quick Look框架判斷文檔是否能被另一個(gè)app打開(kāi)和預(yù)覽。
UIDocumentInteractionController在iOS3.2中就已經(jīng)存在了,使用起來(lái)非常靈活,功能也比較強(qiáng)大。它除了支持同設(shè)備上app之間的文檔共享外,還可以實(shí)現(xiàn)文檔的預(yù)覽、打印、發(fā)郵件以及復(fù)制。
要使用一個(gè)文件交互控制器(UIDocumentInteractionController類的實(shí)例),需要以下步驟:
為每個(gè)你想打開(kāi)的文件創(chuàng)建一個(gè)UIDocumentInteractionController類的實(shí)例
實(shí)現(xiàn)UIDocumentInteractionControllerDelegate代理
顯示預(yù)覽窗口/顯示菜單。
一、創(chuàng)建實(shí)例
DocumentInteraction Controller使用靜態(tài)方法interactionControllerWithURL創(chuàng)建實(shí)例,這個(gè)方法使用一個(gè)NSURL作為參數(shù)。
//創(chuàng)建實(shí)例NSURL*filePath = [NSURLfileURLWithPath:path];UIDocumentInteractionController*documentController = [UIDocumentInteractionControllerinteractionControllerWithURL:[NSURLfileURLWithPath:filePath]];
二、顯示預(yù)覽窗口
Document Interaction Controller對(duì)象使用presentPreviewAnimated方法彈出一個(gè)全屏的文檔預(yù)覽窗口。
BOOLb = [documentController presentPreviewAnimated:YES];
三、顯示菜單
如果你不想在本應(yīng)用里面打開(kāi)文件,那么可以通過(guò)第三方應(yīng)用打開(kāi)預(yù)覽文件。通過(guò)OptionsMenu(選項(xiàng)菜單),顯示能夠接收該類型文件的應(yīng)用,由用戶選擇相應(yīng)的操作。
顯示菜單可以使用下列方法:
- presentOptionsMenuFromRect:inView:animated:
- presentOptionsMenuFromBarButtonItem:animated:
- presentOpenInMenuFromRect:inView:animated:
- presentOpenInMenuFromBarButtonItem:animated:
這些方法都是類似的,只是顯示位置有區(qū)別而已。以下代碼演示其中一個(gè)方法的使用。
CGRect navRect = self.navigationController.navigationBar.frame;
navRect.size = CGSizeMake(1500.0f, 40.0f);
[documentController presentOptionsMenuFromRect:navRect
inView:self.view
animated:YES];
四、使用委托
如果你顯示一個(gè)Document Interaction Controller ,則必需要為delegate屬性用指定一個(gè)委托。讓委托告訴DocumentInteraction Controller如何顯示。
documentController.delegate = self;
委托對(duì)象需要實(shí)現(xiàn)一系列委托方法,最常見(jiàn)的包括:
- documentInteractionControllerViewControllerForPreview:
- documentInteractionControllerViewForPreview:
- documentInteractionControllerRectForPreview:
這3個(gè)方法在用戶點(diǎn)擊“快速查看”菜單時(shí)依次調(diào)用。
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller {
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller {
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller {
return self.view.frame;
}
//點(diǎn)擊預(yù)覽窗口的“Done”(完成)按鈕時(shí)調(diào)用
- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller {
}
功能一:分享文件
- (void)shareFile {NSString*filePath = [[NSBundlemainBundle] pathForResource:@"皮卡丘"ofType:@"jpeg"];//創(chuàng)建實(shí)例UIDocumentInteractionController*documentController = [UIDocumentInteractionControllerinteractionControllerWithURL:[NSURLfileURLWithPath:filePath]];//設(shè)置代理documentController.delegate =self;BOOLcanOpen = [documentController presentOpenInMenuFromRect:CGRectZeroinView:self.view? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? animated:YES];if(!canOpen) {NSLog(@"沒(méi)有程序可以打開(kāi)要分享的文件");? ? }}
功能二:預(yù)覽文件(注冊(cè)應(yīng)用程序支持的文件類型)
- (void)preview {if(!_path) {return;? ? }NSURL*fileURL = [NSURLURLWithString:[NSStringstringWithFormat:@"%@%@", [selfgetURL], [_path lastPathComponent]]];//創(chuàng)建實(shí)例UIDocumentInteractionController*documentController =? ? [UIDocumentInteractionControllerinteractionControllerWithURL:fileURL];//設(shè)置代理documentController.delegate =self;? ? [documentController presentPreviewAnimated:YES];}
配置Info.plist文件
如果你的程序能夠打開(kāi)某種文件,你可以向系統(tǒng)進(jìn)行注冊(cè)。方便其他程序通過(guò) iOS 的document interaction技術(shù)提供給用戶一個(gè)選擇,從而調(diào)用你的程序處理這些文件。
這需要在程序的Info.plist文件中添加CFBundleDocumentTypes鍵(查看CoreFoundation Keys)。
系統(tǒng)將該鍵中包含的內(nèi)容進(jìn)行登記,這樣其他程序就可以通過(guò)document interaction controller訪問(wèn)到這些信息。
CFBundleDocumentTypes鍵是一個(gè)dictionary數(shù)組,每個(gè)dictionary表示了一個(gè)指定的文檔類型。一個(gè)文檔類型通常與某種文件類型是一一對(duì)應(yīng)的。
但是,如果你的程序?qū)Χ鄠€(gè)文件類型采用同樣的處理方式,你也可以把這些類型都分成一個(gè)組,統(tǒng)一視作一個(gè)文檔類型。例如,你的程序中使用到的本地文檔類型,有一個(gè)是舊格式的,還有一個(gè)新格式(似乎是影射微軟office文檔),則你可以將二者分成一組,都放到同一個(gè)文檔類型下。這樣,舊格式和新格式的文件都將顯示為同一個(gè)文檔類型,并以同樣的方式打開(kāi)。
CFBundleDocumentTypes數(shù)組中的每個(gè) dictionary 可能包含以下鍵:
CFBundleTypeName
指定文檔類型名稱。
CFBundleTypeIconFiles
是一個(gè)數(shù)組,包含多個(gè)圖片文件名,用于作為該文檔的圖標(biāo)。
LSItemContentTypes
是一個(gè)數(shù)組,包含多個(gè)UTI【Uniform Type Identifiers】類型的字符串。UTI類型是本文檔類型(組)所包含的文件類型。
LSHandlerRank
表示應(yīng)用程序是“擁有”還是僅僅是“打開(kāi)”這種類型而已。
下表列出了Info.plist中的一個(gè)CFBundleTypeName官方示例。
自定義文件格式的文檔類型
CFBundleTypeName
My File Format
CFBundleTypeIconFiles
MySmallIcon.png
MyLargeIcon.png
LSItemContentTypes
com.example.myformat
LSHandlerRank
Owner
自己程序配置文件
CFBundleDocumentTypes
CFBundleTypeName
com.myapp.common-data
LSItemContentTypes
com.microsoft.powerpoint.ppt
public.item
com.microsoft.word.doc
com.adobe.pdf
com.microsoft.excel.xls
public.image
public.content
public.composite-content
public.archive
public.audio
public.movie
public.text
public.data
打開(kāi)支持的文件類型
你可以在應(yīng)用程序委托的application:didFinishLaunchingWithOptions:方法中獲得該文件的信息。如果你的程序要處理某些自定義的文件類型,你必須實(shí)現(xiàn)這個(gè)委托方法(而不是applicationDidFinishLaunching: 方法) 并用這個(gè)方法啟動(dòng)應(yīng)用程序。
application:didFinishLaunchingWithOptions:方法的option參數(shù)包含了要打開(kāi)的文件的相關(guān)信息。尤其需要在程序中關(guān)心下列鍵:
UIApplicationLaunchOptionsURLKey
包含了該文件的NSURL。
UIApplicationLaunchOptionsSourceApplicationKey
包含了發(fā)送請(qǐng)求的應(yīng)用程序的 Bundle ID。
UIApplicationLaunchOptionsAnnotationKey
包含了源程序向目標(biāo)程序傳遞的與該文件相關(guān)的屬性列表對(duì)象。
如果UIApplicationLaunchOptionsURLKey鍵存在,你的程序應(yīng)當(dāng)立即用該 URL 打開(kāi)該文件并將內(nèi)容呈現(xiàn)給用戶。其他鍵可用于收集與打開(kāi)的文件相關(guān)的參數(shù)和信息。
如果你的應(yīng)用程序處于活躍狀態(tài),此時(shí)application:didFinishLaunchingWithOptions:方法是不會(huì)被調(diào)用的。需要實(shí)現(xiàn)application:openURL:options:方法
【以下是本人的寫(xiě)法】
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {? ? _vc = [[ViewController alloc] init];UINavigationController*nav? ? = [[UINavigationControlleralloc] initWithRootViewController:_vc];self.window? ? ? ? ? ? ? ? ? ? = [[UIWindowalloc] initWithFrame:[UIScreenmainScreen].bounds];self.window.backgroundColor? ? = [UIColorwhiteColor];self.window.rootViewController = nav;? ? [self.window makeKeyAndVisible];if(launchOptions) {NSString*str = [NSStringstringWithFormat:@"\n發(fā)送請(qǐng)求的應(yīng)用程序的 Bundle ID:%@\n\n文件的NSURL:%@\n\n文件相關(guān)的屬性列表對(duì)象:%@",? ? ? ? ? ? ? ? ? ? ? ? launchOptions[UIApplicationLaunchOptionsSourceApplicationKey],? ? ? ? ? ? ? ? ? ? ? ? launchOptions[UIApplicationLaunchOptionsURLKey],? ? ? ? ? ? ? ? ? ? ? ? launchOptions[UIApplicationLaunchOptionsSourceApplicationKey]];? ? ? ? [[[UIAlertViewalloc] initWithTitle:@""message:str? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:nilcancelButtonTitle:@"確定"otherButtonTitles:nil,nil] show];? ? ? ? _vc.path = [launchOptions[UIApplicationLaunchOptionsURLKey] description];? ? ? ? [_vc preview];? ? }returnYES;}- (BOOL)application:(UIApplication*)application openURL:(nonnullNSURL*)url options:(nonnullNSDictionary *)options {if(options) {NSString*str = [NSStringstringWithFormat:@"\n發(fā)送請(qǐng)求的應(yīng)用程序的 Bundle ID:%@\n\n文件的NSURL:%@", options[UIApplicationOpenURLOptionsSourceApplicationKey], url];? ? ? ? [[[UIAlertViewalloc] initWithTitle:@""message:str? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:nilcancelButtonTitle:@"確定"otherButtonTitles:nil,nil] show];? ? ? ? _vc.path = [url description];? ? ? ? [_vc preview];? ? }returnYES;}