8

我一直在使用+[NSURL fileURLWithPath:]它,因为它很方便,但在分析中我发现这是瓶颈的来源,因为它在调用+[NSURL fileURLWithPath:isDirectory:](或 Core Foundation 等效项)之前会查询文件系统:

path如果它以斜杠结尾,则此方法假定它是一个目录。如果path不以斜线结尾,则该方法检查文件系统以确定path是文件还是目录。如果path存在于文件系统中并且是一个目录,则该方法附加一个尾部斜杠。如果path文件系统中不存在,则该方法假定它表示文件并且不附加尾部斜杠。

如果可能的话,我想避免这种开销。但我并不总是提前知道我正在构建的 URL 是否是目录。例如,可能只给我一个路径,或者给我一个目录和其中的项目(未知类型)的名称。我的问题是,即使结果可能不准确,总是忽略NO是否可以?isDirectory

特别是,我想确保这不会搞砸-[NSURL getResourceValue:forKey:error:]并且NSFileManager.

一些基本测试并没有发现这种优化有任何不良后果,但这并不意味着没有。我并不完全清楚为什么 NSURL首先关心isDirectory。查看CFURL 源代码,代码似乎试图确保目录路径始终以斜杠结尾。但是,除了出于显示目的之外,我不清楚为什么这对文件系统路径很重要。NSString(在使用来表示路径时,这从来都不是问题。)文档+[NSURL fileURLWithPath:isDirectory:]isDir是:

一个布尔值,指定path在解析相对路径组件时是否将其视为目录路径。YES如果路径指示目录则通过,否则NO

事实上,如果我使用-[NSURL initWithString:relativeToURL:],新的 URL 不包括最后一个组件,baseURL除非它是用YESfor创建的isDirectory。但是,我认为我从未调用过此方法,而且系统似乎不需要代表我这样做(对于上述用例)。我注意到-[NSURL URLByAppendingPathComponent:] 在必要时插入斜杠,而不是假设IS_DIRECTORY标志是正确的。那么,除了创建相对 URL 之外,这个标志是否重要?即使我愿意,在一般情况下似乎也不可能总是传递正确的值。文件系统总是可以从我下面改变。如果我使用该路径,系统也无法始终确定它,+[NSURL fileURLWithPath:]因为文件系统中可能尚不存在该路径。

4

3 回答 3

0

如果您传入NO并始终创建非目录 URL,那么对于使用 URL 访问文件系统的任何例程(例如-getResourceValue:forKey:error:NSFileManager)来说,这绝对没问题。

对于fileURL,只有在您想要针对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];

在实践中,处理fileURL 的相对字符串/路径往往并不是那么普遍。远程 URL 更需要它(当然取决于您的应用程序做什么!)

于 2013-09-25T09:37:36.230 回答
0

这是一个重要的例子

于 2018-01-28T00:54:20.650 回答
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 应该被视为一个提示,开发人员应该记住 fileURLWithPath: 和 fileURLWithPath:isDirectory: 将根据 URL 的沙盒状态生成不同的路径。

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

于 2021-01-15T12:47:40.090 回答