2009-10-14 21 views
73

我發佈這個問題,因爲我有一個完整的答案寫出來的另一篇文章,當我發現它不適用於原來的,但我認爲是太浪費了太有用。因此,我也將此作爲社區維基,以便其他人可以充實問題和答案。如果您發現答案有用,請將問題投票 - 作爲社區wiki我不應該得到這個投票的積分,但它會幫助其他人找到它如何在iPhone上獲得可寫路徑?

如何獲得允許文件寫入的路徑iPhone?您可以(誤導性地)在模擬器上的任意位置進行書寫,但在iPhone上,您只能寫入特定位置。

回答

184

有三種類型的可寫路徑考慮 - 首先是文檔,在那裏你將想要保留和提供給用戶的東西通過iTunes(如3.2):

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 

其次,和Documents目錄非常相似,還有Library文件夾,您可以在其中存儲配置文件和可寫數據庫,但您不希望用戶能夠通過iTunes混淆:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); 
NSString *libraryDirectory = [paths objectAtIndex:0]; 

請注意,即使用戶使用早於3.2版本的設備(iPad)無法在iTunes中查看文件,NSLibraryDirectory常量自iPhoneOS 2.0開始可用,因此可用於定位3.0的構建(如果仍然這樣做,甚至更早)。此外,除非您將應用程序標記爲允許用戶修改文檔,否則用戶將無法看到任何內容,因此如果您今天使用文檔,則只要在更新用於支持用戶文檔的位置時更改位置即可。

最後有一個緩存目錄,在那裏你可以把你不在乎存在長期或沒有(手機可能在某一時刻將其刪除)圖片:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
NSString *cachePath = [paths objectAtIndex:0]; 
BOOL isDir = NO; 
NSError *error; 
if (! [[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) { 
    [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:&error]; 
} 

請注意,您必須在那裏創建Caches目錄,所以在編寫時你必須檢查和創建每一次!有點痛,但事實就是這樣。

然後,當你有一個可寫的路徑,你只是附加一個文件名到它像這樣:

NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"SomeDirectory/SomeFile.txt"]; 

NSString *filePath = [cachePath stringByAppendingPathComponent:@"SomeTmpFile.png"]; 

使用該路徑讀取或寫入。

請注意,您可以在上述示例字符串中的一個(假定已創建一個)的可寫路徑中創建子目錄。

如果您要將圖像寫入照片庫,則不能使用文件系統調用來執行此操作 - 相反,您必須在內存中使用UIImage,並使用由UIKit定義的UIImageWriteToSavedPhotosAlbum()函數調用。您無法控制目標格式或壓縮級別,也無法以此方式附加任何EXIF。

+6

不要構建路徑緩存你自己。使用相同的'NSSearchPathForDirectoriesInDomain()'函數,而不是使用'NSDocumentDirectory',使用'NSCachesDirectory'。 – 2009-10-14 15:43:50

+0

編輯答案使用'NSCachesDirectory' – 2009-10-14 15:46:20

+0

謝謝,很高興知道。 – 2009-10-14 16:12:08

5

感謝肯達爾&戴夫,以上,我認爲這個修正案是有用的提出來。當使用一次性調試代碼,我用this trick邁克灰的NSBlog消除臨時變量ISDIR &錯誤,最大限度地減少線的數量,使得冗長几乎可以忍受的:

NSFileHandle *dumpFileHandle = nil; 
#ifdef DEBUG 
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&(BOOL){0}]) 
     [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:YES attributes:nil error:&(NSError*){nil}]; 
    NSString *dumpPath = [cachePath stringByAppendingPathComponent:@"dump.txt"]; 
    [[NSFileManager defaultManager] createFileAtPath:dumpPath contents:nil attributes:nil]; 
    [(dumpFileHandle = [NSFileHandle fileHandleForWritingAtPath:dumpPath]) truncateFileAtOffset:0]; 
#endif 

if (dumpFileHandle) [dumpFileHandle writeData:blah];