試想有這么一款游戲:里面有山有水州藕,有車有房束世,有鐵軌公路,你在里面上天入海床玻,殺人放火毁涉,駕飛機(jī),開坦克锈死,你似乎擁有整個(gè)世界贫堰,而另一個(gè)玩家也有同樣的幻覺;對于游戲主機(jī)來說待牵,不過是給你們每人一個(gè)“盒子”其屏,一個(gè)微觀盆景罷了,你的胡作非為缨该,對其他玩家不會(huì)造成任何影響偎行。這便是沙盒,一種文件訪問權(quán)限的隔離機(jī)制贰拿。
每個(gè)應(yīng)用都有相同的文件目錄睦优,對自己目錄下的修改不會(huì)對其它應(yīng)用造成影響。
換句話說壮不,應(yīng)用也不能通過相同的路徑訪問到其它應(yīng)用的文件汗盘,這與我們在PC機(jī)下常用文件共享有很大的差別。
沙盒中各個(gè)文件夾的差別
每個(gè)應(yīng)用默認(rèn)都有以下文件夾询一,如下圖所示:
每個(gè)目錄的功能有以下差別:
每個(gè)文件夾的“能力”各有差別隐孽,以適用不同的使用場景,Document/適合用戶生成的健蕊,需要備份菱阵、共享的數(shù)據(jù),如文件工具生成的Doc類文檔缩功。
Library/適合后臺記錄值晴及,但用戶無需看到的數(shù)據(jù),比如服務(wù)器同步數(shù)據(jù)嫡锌,緩存數(shù)據(jù)庫文件等虑稼。
根目錄新建其它文件夾會(huì)怎么樣?
可以建任意文件夾及文件势木,但備份等行為并不保證蛛倦,比如iOS8下無法在根目錄建立文件夾,iOS9卻可以啦桌,不要依賴這種不確定的系統(tǒng)行為溯壶。
如何查看沙盒文件
查看模擬器沙盒:
- APP工程里加入以下代碼:
NSString *homeDirectory = NSHomeDirectory();
NSLog(@"path:%@", homeDirectory);
控制臺輸出的路徑如下
/Users/[用戶名]/Library/Developer/CoreSimulator/Devices/04D49FFD-11F6-4A1E-BE74-D7C3A1AD1D40/data/Containers/Data/Application/20DE6878-D29E-431C-BAC1-78B4A85F51D3/Documents
20DE6878-D29E-431C-BAC1-78B4A85F51D3 這串字母數(shù)字
每次應(yīng)用啟動(dòng)都會(huì)變化,小心不要被先前的路徑誤導(dǎo)
-
打開Finder
查看真機(jī)沙盒
編程訪問各文件夾的方法
訪問Home
見上文 查看模擬器沙盒
訪問Document
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
NSLog(@"The document's path:%@", documentPath);
這里返回的數(shù)組在iOS平臺上總是只有一個(gè)對象
更換以上NSDocumentDirectory的枚舉值,可獲得其它沙盒目錄路徑
NSLibraryDirectory //.../Library/
NSCachesDirectory //.../Library/Caches/
NSString *tempPath = NSTemporaryDirectory(); //.../tmp/
NSLog(@"tempPath:%@", tempPath);
獲得安裝包中的文件路徑
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@”apple” ofType:@”png”];
突破沙盒
1. 在程序間共享文檔
可以通過UIDocumentInteractionController
將文件分享給其它應(yīng)用:
- (void)shareFile {
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"我的圖片" ofType:@"jpeg"]; //創(chuàng)建實(shí)例
UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]]; //設(shè)置代理
documentController.delegate = self;
BOOL canOpen = [documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
if (!canOpen) {
NSLog(@"沒有程序可以打開要分享的文件");
}
}
注冊自己能打開的文件:
這需要在程序的Info.plist文件中添加CFBundleDocumentTypes鍵, 它是一個(gè)dictionary數(shù)組且改,每個(gè)dictionary表示了一個(gè)指定的文檔類型验烧。
數(shù)組中的每個(gè) dictionary 可能包含以下鍵:
CFBundleTypeName
指定文檔類型名稱。
CFBundleTypeIconFiles
是一個(gè)數(shù)組又跛,包含多個(gè)圖片文件名噪窘,用于作為該文檔的圖標(biāo)。
LSItemContentTypes
是一個(gè)數(shù)組效扫,包含多個(gè)UTI類型的字符串倔监。UTI
類型是本文檔類型(組)所包含的文件類型。
LSHandlerRank
表示應(yīng)用程序是“擁有”還是僅僅是“打開”這種類型而已菌仁。
一個(gè)plist文件中的例子:
<dict>
<key>CFBundleTypeName</key>
<string>My File Format</string>
<key>CFBundleTypeIconFiles</key>
<array>
<string>MySmallIcon.png</string>
<string>MyLargeIcon.png</string>
</array>
<key>LSItemContentTypes</key>
<array>
<string>com.example.myformat</string>
</array>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
響應(yīng)其它應(yīng)用的打開文件請求:
實(shí)現(xiàn)application:didFinishLaunchingWithOptions:
方法中獲得該文件的信息浩习,而不是applicationDidFinishLaunching
如果你的應(yīng)用程序處于活躍狀態(tài),此時(shí)application:didFinishLaunchingWithOptions:
方法是不會(huì)被調(diào)用的济丘。需要實(shí)現(xiàn)application:openURL:options:
方法