如何在iPhone上获得可写路径?


73

我发布此问题的原因是,我有完整的答案写在另一篇文章中,当时我发现它不适用于原始文章,但我认为它太有用了,无法浪费。因此,我也将其设为社区Wiki,以便其他人可以充实问题和答案。如果您认为答案有用,请对问题进行投票-作为社区Wiki,我不应该为此投票而获得积分,但是它将帮助其他人找到它

如何获得iPhone上允许写入文件的路径?您可以(误导)在Simulator上任何您喜欢的地方写东西,但是在iPhone上,您只能写到特定位置。

Answers:


186

有三种可写路径可供考虑-第一种是“文档”,您可以在其中存储要保留的内容并通过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中查看文件,但自iPhoneOS 2.0起,NSLibraryDirectory常量就可用了,因此可以用于目标3.0的构建(如果仍在使用,则更早)那)。此外,除非您将应用程序标记为允许用户修改文档,否则用户将看不到任何内容。因此,如果您今天使用的是Documents,则可以在更新支持用户文档的位置时更改位置。

最后一个缓存目录,您可以在其中放置您不需要的图像是否长期存在(电话可能会在某些时候删除它们):

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,并使用UIImageWriteToSavedPhotosAlbum()UIKit定义的函数调用。您无法控制目标格式或压缩级别,并且无法以这种方式附加任何EXIF。


6
不要自己构建Cache的路径。使用相同的NSSearchPathForDirectoriesInDomain()功能,但不要NSDocumentDirectory使用NSCachesDirectory
戴夫·德隆

编辑使用答案NSCachesDirectory
Dave DeLong

idevkit.com/iphonedev/2009/09/saving-nsmutablearrays中 有一节介绍如何获取应用程序的文档目录,其中包括xcodeproj。它基于保存nsmutablearray并再次加载它的基础。从本质上来说,这是用于将目录保存到其他对象的相同方法。
Sj。

2
很好,但与问题(与如何获得可写区域有关)是切线的。加上StackOverflow的想法是,它应该充当规范的信息存储库。
肯德尔·赫尔姆斯特·盖尔纳

根据:[iOS应用程序编程指南](developer.apple.com/library/ios/#documentation/iPhone/…),不建议使用NSLibraryDirectory路径,而是苹果建议使用NSApplicationSupportDirectory。也许应该更新Wiki以反映这一点?
hwaxxer 2011年

5

感谢上面的Kendall&Dave,我认为提出这一修正案很有用。当使用一次性调试代码,我用这一招从迈克灰的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];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.