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

时间:2009-10-14 15:37:55

标签: iphone filesystems

我发布这个问题是因为我有一个完整的答案,这篇文章是针对另一篇文章写的,当我发现它不适用于原版时,但我觉得它太浪费了。因此,我也将其作为社区维基,以便其他人可以充实问答。如果您觉得答案有用,请将问题投票 - 作为社区维基我不应该为此投票获得积分,但它会帮助其他人找到它

如何获取iPhone上允许写入文件的路径?您可以(误导性地)在模拟器上随意写任何地方,但在iPhone上,您只能写入特定位置。

2 个答案:

答案 0 :(得分: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中的文件,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。

答案 1 :(得分:5)

感谢Kendall&戴夫,上面,我认为这个修正案对于培养是有用的。当用于一次性调试代码时,我使用来自Mike Ash的this trickNSBlog来消除临时变量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];