1、前言
iOS文件存儲(chǔ)機(jī)制
每個(gè)iOS程序都有一個(gè)獨(dú)立的文件系統(tǒng)(存儲(chǔ)空間),而且只能在對(duì)應(yīng)的文件系統(tǒng)中進(jìn)行操作,此區(qū)域被稱為沙盒。應(yīng)用必須待在自己的沙盒里,其他應(yīng)用不能訪問該沙盒。所有的非代碼文件都要保存在此,例如屬性文件plist、文本文件、圖像、圖標(biāo)、媒體資源等
沙盒中相關(guān)路徑
AppName.app 應(yīng)用程序的程序包目錄,包含應(yīng)用程序的本身。由于應(yīng)用程序必須經(jīng)過簽名,所以不能在運(yùn)行時(shí)對(duì)這個(gè)目錄中的內(nèi)容進(jìn)行修改,否則會(huì)導(dǎo)致應(yīng)用程序無法啟動(dòng)。
Documents/ 保存應(yīng)用程序的重要數(shù)據(jù)文件和用戶數(shù)據(jù)文件等。用戶數(shù)據(jù)基本上都放在這個(gè)位置(例如從網(wǎng)上下載的圖片或音樂文件),該文件夾在應(yīng)用程序更新時(shí)會(huì)自動(dòng)備份,在連接iTunes時(shí)也可以自動(dòng)同步備份其中的數(shù)據(jù)。
Library:這個(gè)目錄下有兩個(gè)子目錄,可創(chuàng)建子文件夾??梢杂脕矸胖媚M粋浞莸幌M挥脩艨吹降臄?shù)據(jù)。該路徑下的文件夾,除Caches以外,都會(huì)被iTunes備份.
Library/Caches: 保存應(yīng)用程序使用時(shí)產(chǎn)生的支持文件和緩存文件(保存應(yīng)用程序再次啟動(dòng)過程中需要的信息),還有日志文件最好也放在這個(gè)目錄。iTunes 同步時(shí)不會(huì)備份該目錄并且可能被其他工具清理掉其中的數(shù)據(jù)。
Library/Preferences: 保存應(yīng)用程序的偏好設(shè)置文件。NSUserDefaults類創(chuàng)建的數(shù)據(jù)和plist文件都放在這里。會(huì)被iTunes備份。
相關(guān)問題
因?yàn)槊總€(gè)app下的沙盒路徑都是封閉的,其他應(yīng)用訪問不到,也就導(dǎo)致了文件不能共享。只能自己在代碼中維護(hù)本app內(nèi)的文件。這給用戶帶來很多的不便。因此,蘋果除了一個(gè)系統(tǒng)的“文件”的app,用來管理app內(nèi)的文件。但是系統(tǒng)的“文件”這個(gè)app不是可以管理全部的app下的文件,他只能管理對(duì)“文件”這個(gè)app開放權(quán)限的APP。
計(jì)劃
最近在做IM開發(fā),涉及到文件傳輸,我們不想做的特別封閉,所以就想可以發(fā)送app以外的文件(比如微信中保存下來的)具體實(shí)現(xiàn)就是:從微信里下載的文件保存到“ fileAPP”內(nèi),然后我們?cè)诎l(fā)送文件時(shí),可以發(fā)送本地文件,也可以發(fā)送“ fileAPP”內(nèi)保存的文件
2、讓自己的app對(duì)“ fileAPP”開放管理權(quán)限
2.1、在Identifiers下選擇你要添加icloud的boundid把icloud配置勾選上

2.2、工程配置

點(diǎn)擊Caoablity左側(cè)的加號(hào),搜索iCloud,然后添加即可
2.3、 設(shè)置info.plist
第一個(gè)是 UIFileSharingEnabled,這個(gè)可以使 iTunes 分享你文件夾內(nèi)的內(nèi)容;第二個(gè)是 LSSupportsOpeningDocumentsInPlace ,它保證了你文件夾內(nèi)本地文件的獲取權(quán)限,你需要將這兩個(gè)鍵值對(duì)的值設(shè)置為 YES
以上設(shè)置完,重新運(yùn)行app之后,在系統(tǒng)的“ fileAPP”中會(huì)出現(xiàn)一個(gè)以你的APP命名的文件夾,里面包含了APP內(nèi)沙盒的目錄和文件
但是這里面的文件很亂,而且會(huì)將沙盒內(nèi) Documents 文件夾內(nèi)的所有文件都顯示出來
2.4、如何在fileAPP里隱藏重要的文件?
如果它不是那么重要的,我們可以將它們存放在 cachesDirectory 或者是 temporaryDirectory 文件夾下面;如果它是重要的文件,大多數(shù)情況下,我們是需要將它們備份在 iCloud 上的,這樣的文件我們建議將它存放在 applicationSupportDirectory 目錄下

以上,是將自己的文件共享給 fileAPP
3、app如何獲取到“文件”app下管理的文件到本app內(nèi)
3.1、調(diào)起fileAPP 文件目錄
//打開文件APP
- (void)presentDocumentCloud {
NSArray *documentTypes = @[@"public.content", @"public.text", @"public.source-code ", @"public.image", @"public.audiovisual-content", @"com.adobe.pdf", @"com.apple.keynote.key", @"com.microsoft.word.doc", @"com.microsoft.excel.xls", @"com.microsoft.powerpoint.ppt"];
UIDocumentPickerViewController *documentPickerViewController = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:documentTypes inMode:UIDocumentPickerModeOpen];
documentPickerViewController.delegate = self;
[self presentViewController:documentPickerViewController animated:YES completion:nil];
}
這里的documentTypes數(shù)組內(nèi)設(shè)置要拿的文件格式
UIDocumentPickerMode有四種:
typedef NS_ENUM(NSUInteger, UIDocumentPickerMode) {
UIDocumentPickerModeImport,
UIDocumentPickerModeOpen,
UIDocumentPickerModeExportToService,
UIDocumentPickerModeMoveToService
} API_DEPRECATED("Use appropriate initializers instead",ios(8.0,14.0)) API_UNAVAILABLE(tvOS);
UIDocumentPickerModeImport : 將文件拿出來UIDocumentPickerModeOpen:打開文件
后面是將文件傳到fileAPP內(nèi)的操作,類似于微信的保存文件到fileAPP內(nèi)的操作。這里官方文檔之給了前兩個(gè),后面的我們也沒涉及到,以后研究吧。
3.2、設(shè)置代理
<UIDocumentPickerDelegate, UIDocumentInteractionControllerDelegate>
3.3、實(shí)現(xiàn)代理
#pragma mark - UIDocumentPickerDelegate
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {
BOOL fileUrlAuthozied = [url startAccessingSecurityScopedResource];
if (fileUrlAuthozied && [self iCloudEnable]) {
//通過文件協(xié)調(diào)工具來得到新的文件地址,以此得到文件保護(hù)功能
NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];
NSError *error;
[fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
//讀取文件
NSString *fileName = [newURL lastPathComponent];
fileName = [fileName stringByRemovingPercentEncoding];
NSData * data = [NSData dataWithContentsOfURL:newURL];
self.completionBlock(data,fileName);
self.completionBlock = nil;
}];
[url stopAccessingSecurityScopedResource];
}
}
這里需要將拿到的url做處理,應(yīng)為這里拿到的url是fileAPP文件的本地文件路徑,在自己的app內(nèi)通過[NSData dataWithContentsOfURL:url]方法是無法拿到數(shù)據(jù)的,應(yīng)該是只能拿自己沙盒文件路徑的設(shè)置的原因。
[fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
}];
這么處理后,拿到的newUrl就是本地的路徑了,通過[NSData dataWithContentsOfURL:url]即可拿到文件data。
之后即可對(duì)文件進(jìn)行發(fā)送上傳等操作。