【问题标题】:Create folder/directory in Objective-C/cocoa在 Objective-C/cocoa 中创建文件夹/目录
【发布时间】:2011-07-05 13:26:40
【问题描述】:

我有这段代码用于在 Objective-C/cocoa 中创建文件夹/目录。

if(![fileManager fileExistsAtPath:directory isDirectory:&isDir])
        if(![fileManager createDirectoryAtPath:directory attributes:nil])
            NSLog(@"Error: Create folder failed %@", directory);

它工作正常,但我收到了creatDirectoryAtPath:attributes is deprecated 警告消息。 在 Cocoa/Objective-c 中制作目录构建器的最新方法是什么?

已解决

BOOL isDir;
NSFileManager *fileManager= [NSFileManager defaultManager]; 
if(![fileManager fileExistsAtPath:directory isDirectory:&isDir])
    if(![fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:NULL])
        NSLog(@"Error: Create folder failed %@", directory);

【问题讨论】:

标签: objective-c cocoa directory


【解决方案1】:
【解决方案2】:

我想补充一点,并从文档中提到更多关于使用 +defaultManager 方法的内容:

在 iOS 和 Mac OS X v 10.5 及更高版本中,您应该考虑使用 [[NSFileManager alloc] init] 而不是单例方法 defaultManager。 NSFileManager 的实例在使用 [[NSFileManager alloc] init] 创建时被认为是线程安全的。

【讨论】:

  • 使用defaultManager 是安全的。 “共享的 NSFileManager 对象的方法可以安全地从多个线程调用。但是,如果您使用委托来接收有关移动、复制、删除和链接操作状态的通知,您应该创建文件管理器的唯一实例对象,将您的委托分配给该对象,并使用该文件管理器来启动您的操作。”
【解决方案3】:

您可能更喜欢使用NSFileManager 方法:

createDirectoryAtURL:withIntermediateDirectories:attributes:error:

它适用于 URL 而不是路径字符串。

【讨论】:

    【解决方案4】:

    您的解决方案是正确的,尽管 Apple 在 NSFileManager.h 中包含了一个重要说明:

    /* The following methods are of limited utility. Attempting to predicate behavior 
    based on the current state of the filesystem or a particular file on the 
    filesystem is encouraging odd behavior in the face of filesystem race conditions. 
    It's far better to attempt an operation (like loading a file or creating a 
    directory) and handle the error gracefully than it is to try to figure out ahead 
    of time whether the operation will succeed. */
    
    - (BOOL)fileExistsAtPath:(NSString *)path;
    - (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory;
    - (BOOL)isReadableFileAtPath:(NSString *)path;
    - (BOOL)isWritableFileAtPath:(NSString *)path;
    - (BOOL)isExecutableFileAtPath:(NSString *)path;
    - (BOOL)isDeletableFileAtPath:(NSString *)path;
    

    本质上,如果多个线程/进程同时修改文件系统,则状态可能会在调用fileExistsAtPath:isDirectory: 和调用createDirectoryAtPath:withIntermediateDirectories: 之间发生变化,因此在这种情况下调用fileExistsAtPath:isDirectory: 是多余的并且可能很危险。

    根据您的需要并在您问题的有限范围内,这可能不是问题,但以下解决方案既简单又减少了未来出现问题的可能性:

    NSFileManager *fileManager= [NSFileManager defaultManager];
    NSError *error = nil;
    if(![fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:&error]) {
         // An error has occurred, do something to handle it
         NSLog(@"Failed to create directory \"%@\". Error: %@", directory, error);
    }
    

    另请注意Apple's documentation:

    返回值

    如果创建了目录,则为YES,如果设置了createIntermediates,则为YES 并且该目录已经存在),如果发生错误,则为 NO。

    因此,将createIntermediates 设置为YES,您已经这样做了,实际上是检查目录是否已经存在。

    【讨论】:

    • 此答案应标记为已接受,因为它包含更多详细信息并且是正确答案:如果您有“withIntermediateDirectories:YES”,则不必使用 fileExistsAtPath
    • 这确实是最好的答案。为清楚起见,如果您不想覆盖目录,请设置 withIntermediateDirectories:NO。这将记录在错误中。
    • 谢谢!我正在寻找有关该主题的一些说明。
    • 在 Swift 中将withIntermediateDirectories 设置为true 时提供目录是否已经存在的事实检查。 (createDirectory(at: someUrl, withIntermediateDirectories: true)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 2012-08-13
    相关资源
    最近更新 更多