+[NSURL fileURLWithPath:isDirectory:]中的isDirectory参数需要正确吗?

8
我一直使用+[NSURL fileURLWithPath:],因为它很方便,但在性能分析中发现这是瓶颈的源头,因为它会在调用+[NSURL fileURLWithPath:isDirectory:](或Core Foundation等效函数)之前查询文件系统:
这个方法假设如果路径以斜杠结尾,则path是目录。 如果path不以斜杠结尾,则该方法会检查文件系统以确定path是文件还是目录。 如果path存在于文件系统中并且是目录,则该方法会追加一个尾随斜杠。如果path不存在于文件系统中,则该方法假设它表示一个文件,并且不追加尾随斜杠。
如果可能的话,我想避免这种开销。 但我并不总是提前知道我正在构建的URL是否为目录。例如,我可能只会得到一个路径或者我可能会得到一个目录和其中一个未知类型的项目的名称。我的问题是,是否可以始终传递NOisDirectory,即使这可能不准确?
特别是,我想确保这不会影响-[NSURL getResourceValue:forKey:error:]NSFileManager
一些基本测试没有显示出这种优化的任何不良后果,但这并不意味着没有。我不完全清楚为什么NSURL在第一次关注isDirectory。查看CFURL源代码,该代码似乎尝试确保目录路径始终以斜杠结尾。但是,除了用于显示目的之外,对我来说不清楚为什么这对文件系统路径很重要。(使用NSString表示路径时从未出现过此问题。)+[NSURL fileURLWithPath:isDirectory:]的文档指出isDir是:
一个布尔值,指定在与相对路径组件解析时path是否被视为目录路径。如果路径指示一个目录,则传递YES,否则传递NO

实际上,如果我使用-[NSURL initWithString:relativeToURL:],除非使用isDirectoryYES值创建了baseURL,否则新URL不会包含baseURL的最后一个组件。但是,我不认为我曾经调用过这种方法,并且似乎系统也不需要代表我这样做(对于上述用例)。我注意到-[NSURL URLByAppendingPathComponent:]会在必要时插入斜杠,而不是假设IS_DIRECTORY标志是正确的。那么,除了创建相对URL外,这个标志有什么作用吗?即使我想这样做,在一般情况下始终传递正确的值似乎也不可能。文件系统可能总是在我身下更改。如果我使用+[NSURL fileURLWithPath:],因为路径在文件系统中可能还不存在,所以系统也不能始终确定它。

3个回答

0

不需要正确设置isDirectory参数,根据我的经验。相反,将isDirectory参数设置为YES并不能保证url.path以文件夹斜杠结尾。

我进行了一些测试,并了解到这完全取决于fileURLWithPath:能否在文件系统中验证,在沙盒应用程序中可能并不总是可能的。

这就解释了为什么在沙盒应用程序中进行此测试得分完美,即使这不是人们所希望的行为:

- (void)testFileURLWithPathIsDirectory
{
    NSString *path = NSHomeDirectory();
    XCTAssertTrue([path isEqualToString:@"/Users/myUser"], @"%@", path);
    
    NSURL *pathURL = [NSURL fileURLWithPath:NSHomeDirectory() isDirectory:YES];
    XCTAssertTrue([pathURL.path isEqualToString:@"/Users/myUser"], @"%@", pathURL.path);
    
    XCTAssertFalse([pathURL.path isEqualToString:@"file:///Users/myUser/"], @"%@", pathURL.path);
}

显然,isDirectory 应该被视为一个提示,开发者应该记住,根据 URL 的沙盒状态,fileURLWithPath 和 fileURLWithPath:isDirectory: 将产生不同的路径。

最后一个需要注意的是:指向包的 URL 的路径永远不会有尾随斜杠,但如果 URL 指向包中的文件,则该路径将显示包是一个目录。


0
如果您传入NO并始终创建非目录URL,则对于使用URL访问文件系统的任何例程(例如-getResourceValue:forKey:error:NSFileManager),这是绝对可以接受的。

对于file URL,只有在您想要解析路径相对于 URL时,尾随斜杠才真正变得重要。也就是说,这段代码片段:

NSURL *baseURL = [NSURL fileURLWithPath:path isDirectory:YES];
NSURL *result = [NSURL URLWithString:@"relative/path" relativeToURL:baseURL];

将会产生不同的结果:

NSURL *baseURL = [NSURL fileURLWithPath:path isDirectory:NO];
NSURL *result = [NSURL URLWithString:@"relative/path" relativeToURL:baseURL];

实际上,在处理file URL的相对字符串/路径时,通常并不是很常见。远程URL需要它更多(当然这取决于您的应用程序要做什么!)


1
谢谢。听起来你同意我的假设。但是操作系统在执行文件系统操作时,是否确实有记录(承诺)不会创建相对URL? - Michael Tsai

0

这里是一个例子,它很重要。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接