【问题标题】:How to check if a directory exists in Objective-C如何检查Objective-C中是否存在目录
【发布时间】:2011-11-24 09:51:57
【问题描述】:

我猜这是初学者的问题,但我试图检查 iPhone 上的 Documents 文件夹中是否存在目录。我阅读了文档并想出了这段代码,不幸的是,该代码在 BOOL fileExists 行中因 EXC_BAD_ACCESS 而崩溃:

 -(void)checkIfDirectoryAlreadyExists:(NSString *)name
{
    NSFileManager *fileManager = [[NSFileManager alloc] init];

    NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:name];

    BOOL fileExists = [fileManager fileExistsAtPath:path isDirectory:YES];

    if (fileExists)
    {
        NSLog(@"Folder already exists...");
    }

}

我不明白我做错了什么?它对我来说看起来很完美,它当然符合文档,不是吗?任何关于我哪里出错的启示将不胜感激!谢谢。

更新:

还是不行……

  -(void)checkIfDirectoryAlreadyExists:(NSString *)name
{
    NSFileManager *fileManager = [[NSFileManager alloc] init];

    NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:name];

    BOOL isDir;
    BOOL fileExists = [fileManager fileExistsAtPath:path isDirectory:&isDir];

    if (fileExists)
    {


        if (isDir) {

            NSLog(@"Folder already exists...");

        }

    }

}

【问题讨论】:

  • @Legolas 根据文档检查它是否是一个目录。但我想这是我出错的地方。
  • 第二个在什么意义上不起作用,仍然是一个错误的访问?还想从文档中指出:Note: Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended. Doing so can cause odd behavior or race conditions. It's far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed.

标签: iphone objective-c cocoa-touch nsfilemanager


【解决方案1】:

documentation 中查看此方法签名:

- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory

您需要一个指向 BOOL 变量的指针作为参数,而不是 BOOL 本身。 NSFileManager 将记录文件是否在该变量中的目录。例如:

BOOL isDir;
BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDir];
if (exists) {
    /* file exists */
    if (isDir) {
        /* file is a directory */
    }
 }

【讨论】:

  • 非常感谢。我认为苹果应该把你的例子放在他们的文档中——我不理解它们,但现在它们很清楚了——通过你的例子!再次感谢,非常感谢。
  • 实际上,只是尝试实现这一点,但它仍然使我的应用程序崩溃。我更新了上面的代码。有任何想法吗?感谢您的帮助。
  • @n.evermind:很高兴为您提供帮助。是的,示例很重要,但可能会占用太多空间 :-) 不用担心,您最终会习惯于从文档中提取确切信息。另外,请注意,Apple 为这种方法提供了一个涉及目录部分的示例。回到问题,我在这里看不到错误,除了创建文件管理器对象的不寻常方式(之前没有注意到)。你有什么特别的理由不使用[NSFileManager defaultManager]?它可能会为您节省一些麻烦。
  • @n.evermind 无论如何它应该可以工作。尝试在BOOL isDir; 行之前放置一个断点,一旦程序在那里停止,在调试器中键入po path。它是否打印正确的值?
  • @sidyll 好点,特别是因为在这种情况下它可以防止内存泄漏。
【解决方案2】:

以防万一有人需要一个 getter,如果它不存在,它会在 Documents 中创建一个文件夹:

- (NSString *)folderPath
{
    if (! _folderPath) {
        NSString *folderName = @"YourFolderName";
        NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectoryPath = [documentPaths objectAtIndex:0];
        _folderPath = [documentsDirectoryPath stringByAppendingPathComponent:folderName];

        // if folder doesn't exist, create it
        NSError *error = nil;
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL isDir;
        if (! [fileManager fileExistsAtPath:_folderPath isDirectory:&isDir]) {
            BOOL success = [fileManager createDirectoryAtPath:_folderPath withIntermediateDirectories:NO attributes:nil error:&error];
            if (!success || error) {
                NSLog(@"Error: %@", [error localizedDescription]);
            }
            NSAssert(success, @"Failed to create folder at path:%@", _folderPath);
        }
    }

    return _folderPath;
}

【讨论】:

    【解决方案3】:

    我有一个实用程序单例类,用于此类事情。由于如果数据库保留在 Documents 中,我无法更新它,我使用此代码将我的 .sqlite 文件从 Documents 复制到 /Library/Private Documents。第一种方法找到库。第二个创建 Private Documents 文件夹(如果它不存在)并将位置作为字符串返回。第二种方法使用与@wzboson 相同的文件管理器方法。

    + (NSString *)applicationLibraryDirectory {
    
                return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
    }
    
    
    + (NSString *)applicationLibraryPrivateDocumentsDirectory {
    
        NSError *error;
        NSString *PrivateDocumentsDirectory = [[self applicationLibraryDirectory] stringByAppendingPathComponent:@"Private Documents"];
    
        BOOL isDir;
        if (! [[NSFileManager defaultManager] fileExistsAtPath:PrivateDocumentsDirectory isDirectory:&isDir]) {
    
            if (![[NSFileManager defaultManager] createDirectoryAtPath:PrivateDocumentsDirectory
                                           withIntermediateDirectories:NO
                                                            attributes:nil
                                                                 error:&error]) {
                NSLog(@"Create directory error: %@", error);
            }
        }
    
        return PrivateDocumentsDirectory;
    }
    

    我在持久存储协调器初始化中这样使用它。但是,相同的原则适用于任何文件。

    NSString *libraryDirectory = [Utilities applicationLibraryPrivateDocumentsDirectory];
    NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:sqliteName];
    NSString *destinationPath = [libraryDirectory stringByAppendingPathComponent:sqliteName];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-07
      • 2013-05-19
      • 2012-09-12
      • 1970-01-01
      • 1970-01-01
      • 2011-10-09
      相关资源
      最近更新 更多