iOS中的沙盒可以讓平臺更加的安全,這也是沙盒給用戶帶來的最主要好處。不過由于沙盒的嚴格限制,導致程序之間共享數據比較麻煩。一般在程序間共享文檔可以通過UIDocumentInteractionController類實現通訊。它支持在你的app中用其他app預覽和顯示文檔。同時也支持文件關聯,允許其他app通過你的程序打開文件。這些技術包括了UIKit中提供的UIDocumentInteractionController類(UIDocumentInteractionController Class Reference),以及Quick Look框架(Quick Look Framework Reference)。
本文將就如何在應用之間進行文件共享進行基本探究。還請大牛勿噴。
效果圖
文件共享
跨APP傳文件
預覽文檔和呈現選項菜單
如果你的app需要打開它不支持的文件(PDF文件、圖像文件,等等),或者需要將app的文件傳輸給另外一個允許接收此類型文件的app時。可以使用文件交互控制器(UIDocumentInteractionController類的實例)為用戶提供可接收程序來處理文件,說的簡單點就是通過Quick Look框架判斷文檔是否能被另一個app打開和預覽。
UIDocumentInteractionController在iOS3.2中就已經存在了,使用起來非常靈活,功能也比較強大。它除了支持同設備上app之間的文檔共享外,還可以實現文檔的預覽、打印、發郵件以及復制。
要使用一個文件交互控制器(UIDocumentInteractionController類的實例),需要以下步驟:
為每個你想打開的文件創建一個UIDocumentInteractionController類的實例
實現UIDocumentInteractionControllerDelegate代理
顯示預覽窗口/顯示菜單。
一、創建實例
DocumentInteraction Controller使用靜態方法interactionControllerWithURL創建實例,這個方法使用一個NSURL作為參數。
//創建實例NSURL*filePath = [NSURLfileURLWithPath:path];UIDocumentInteractionController*documentController = [UIDocumentInteractionControllerinteractionControllerWithURL:[NSURLfileURLWithPath:filePath]];
二、顯示預覽窗口
Document Interaction Controller對象使用presentPreviewAnimated方法彈出一個全屏的文檔預覽窗口。
BOOLb = [documentController presentPreviewAnimated:YES];
三、顯示菜單
如果你不想在本應用里面打開文件,那么可以通過第三方應用打開預覽文件。通過OptionsMenu(選項菜單),顯示能夠接收該類型文件的應用,由用戶選擇相應的操作。
顯示菜單可以使用下列方法:
- presentOptionsMenuFromRect:inView:animated:
- presentOptionsMenuFromBarButtonItem:animated:
- presentOpenInMenuFromRect:inView:animated:
- presentOpenInMenuFromBarButtonItem:animated:
這些方法都是類似的,只是顯示位置有區別而已。以下代碼演示其中一個方法的使用。
CGRect navRect = self.navigationController.navigationBar.frame;
navRect.size = CGSizeMake(1500.0f, 40.0f);
[documentController presentOptionsMenuFromRect:navRect
inView:self.view
animated:YES];
四、使用委托
如果你顯示一個Document Interaction Controller ,則必需要為delegate屬性用指定一個委托。讓委托告訴DocumentInteraction Controller如何顯示。
documentController.delegate = self;
委托對象需要實現一系列委托方法,最常見的包括:
- documentInteractionControllerViewControllerForPreview:
- documentInteractionControllerViewForPreview:
- documentInteractionControllerRectForPreview:
這3個方法在用戶點擊“快速查看”菜單時依次調用。
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller {
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller {
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller {
return self.view.frame;
}
//點擊預覽窗口的“Done”(完成)按鈕時調用
- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller {
}
功能一:分享文件
- (void)shareFile {NSString*filePath = [[NSBundlemainBundle] pathForResource:@"皮卡丘"ofType:@"jpeg"];//創建實例UIDocumentInteractionController*documentController = [UIDocumentInteractionControllerinteractionControllerWithURL:[NSURLfileURLWithPath:filePath]];//設置代理documentController.delegate =self;BOOLcanOpen = [documentController presentOpenInMenuFromRect:CGRectZeroinView:self.view? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? animated:YES];if(!canOpen) {NSLog(@"沒有程序可以打開要分享的文件");? ? }}
功能二:預覽文件(注冊應用程序支持的文件類型)
- (void)preview {if(!_path) {return;? ? }NSURL*fileURL = [NSURLURLWithString:[NSStringstringWithFormat:@"%@%@", [selfgetURL], [_path lastPathComponent]]];//創建實例UIDocumentInteractionController*documentController =? ? [UIDocumentInteractionControllerinteractionControllerWithURL:fileURL];//設置代理documentController.delegate =self;? ? [documentController presentPreviewAnimated:YES];}
配置Info.plist文件
如果你的程序能夠打開某種文件,你可以向系統進行注冊。方便其他程序通過 iOS 的document interaction技術提供給用戶一個選擇,從而調用你的程序處理這些文件。
這需要在程序的Info.plist文件中添加CFBundleDocumentTypes鍵(查看CoreFoundation Keys)。
系統將該鍵中包含的內容進行登記,這樣其他程序就可以通過document interaction controller訪問到這些信息。
CFBundleDocumentTypes鍵是一個dictionary數組,每個dictionary表示了一個指定的文檔類型。一個文檔類型通常與某種文件類型是一一對應的。
但是,如果你的程序對多個文件類型采用同樣的處理方式,你也可以把這些類型都分成一個組,統一視作一個文檔類型。例如,你的程序中使用到的本地文檔類型,有一個是舊格式的,還有一個新格式(似乎是影射微軟office文檔),則你可以將二者分成一組,都放到同一個文檔類型下。這樣,舊格式和新格式的文件都將顯示為同一個文檔類型,并以同樣的方式打開。
CFBundleDocumentTypes數組中的每個 dictionary 可能包含以下鍵:
CFBundleTypeName
指定文檔類型名稱。
CFBundleTypeIconFiles
是一個數組,包含多個圖片文件名,用于作為該文檔的圖標。
LSItemContentTypes
是一個數組,包含多個UTI【Uniform Type Identifiers】類型的字符串。UTI類型是本文檔類型(組)所包含的文件類型。
LSHandlerRank
表示應用程序是“擁有”還是僅僅是“打開”這種類型而已。
下表列出了Info.plist中的一個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
打開支持的文件類型
你可以在應用程序委托的application:didFinishLaunchingWithOptions:方法中獲得該文件的信息。如果你的程序要處理某些自定義的文件類型,你必須實現這個委托方法(而不是applicationDidFinishLaunching: 方法) 并用這個方法啟動應用程序。
application:didFinishLaunchingWithOptions:方法的option參數包含了要打開的文件的相關信息。尤其需要在程序中關心下列鍵:
UIApplicationLaunchOptionsURLKey
包含了該文件的NSURL。
UIApplicationLaunchOptionsSourceApplicationKey
包含了發送請求的應用程序的 Bundle ID。
UIApplicationLaunchOptionsAnnotationKey
包含了源程序向目標程序傳遞的與該文件相關的屬性列表對象。
如果UIApplicationLaunchOptionsURLKey鍵存在,你的程序應當立即用該 URL 打開該文件并將內容呈現給用戶。其他鍵可用于收集與打開的文件相關的參數和信息。
如果你的應用程序處于活躍狀態,此時application:didFinishLaunchingWithOptions:方法是不會被調用的。需要實現application:openURL:options:方法
【以下是本人的寫法】
- (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發送請求的應用程序的 Bundle ID:%@\n\n文件的NSURL:%@\n\n文件相關的屬性列表對象:%@",? ? ? ? ? ? ? ? ? ? ? ? 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發送請求的應用程序的 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;}