NSURL 路径与绝对字符串

Posted

技术标签:

【中文标题】NSURL 路径与绝对字符串【英文标题】:NSURL path vs absoluteString 【发布时间】:2013-04-17 02:44:14 【问题描述】:

我看到很多关于在NSURLNSString 之间转换的问题。它们都涉及使用NSString *path = [myURL absoluteString];NSString *path = [myURL path];这些方法之间的实际区别是什么? 有什么时候应该使用一种方法而不是另一种方法吗?我尝试咨询Apple Docs,但发现它少于有帮助。

我习惯于 URL 仅在有关网站的讨论和其他有关在不同机器之间发送信息的主题中被提及,而在处理单台机器上的文件结构时从未被提及。也许这就是我的一些困惑的来源,因为NSURL 似乎是访问文件的首选方式,无论该文件是否存在于网络或本地设备上。或者,也许这是一个完全不相关的话题。我什至不确定。

【问题讨论】:

我很惊讶这些文档对你没有帮助,因为它们对-path 的用例非常明确。首选absoluteString 作为 URL,如果只是因为 RFC 1808 解析算法。首选 -path 作为文件路径,因为它对格式有多么严格,并且因为文档提到它是获取文件管理器兼容路径的首选方法。 我正要回答这个问题,但 CodaFi 打败了我。 CodaFi,我知道你不需要代表,但你的评论看起来更像是对我的回答。 What is difference between URLWithString and fileURLWithPath of NSURL?的可能重复 【参考方案1】:

问题一:

这些方法之间的实际区别是什么?

让我们来分析一下这 6 行代码 - 3 行用于本地,3 行用于 http URL - 并尝试使用它们。

让我们使用file:// 方案创建一个NSURL。如果您问自己为什么在file: 之后有 3 个/,您应该记住存在一个完整的 URL 方案(file:// 和绝对或相对路径(您可以在RFC 1808 on page 3 中找到有关创建 URL 的更多信息)。我们使用以/ 开头的绝对路径,因此我们以/// 结尾。

NSURL *aLocalURL = [NSURL URLWithString:@"file:///Users/dennis/Desktop/"];
NSLog(@"absolute string: %@", aLocalURL.absoluteString);
NSLog(@"path: %@", aLocalURL.path);

输出:

绝对字符串:file:///Users/dennis/Desktop/ 路径:/Users/dennis/Desktop

所以我们看到absoluteString 仍然知道它的方案,而path 不再有这个信息。

注意:path 是一个文件(目录)URL,在docs 状态下,它的尾部斜杠被剥离。


现在让我们看看远程 URL。对于这些类型的 URL,大多数人都比较熟悉。我们使用与本地 URL 相同的过程来创建它。我们的方案现在是http://,我们的pathwww.apple.com/

NSURL *anHTTPURL = [NSURL URLWithString:@"http://www.apple.com/"];  
NSLog(@"absolute string: %@", anHTTPURL.absoluteString);
NSLog(@"path: %@", anHTTPURL.path);

输出:

绝对字符串:http://www.apple.com/ 路径:/

再次,我们看到绝对字符串仍然知道它的方案,但 path 现在是 /。所以path 在处理远程 URL 时似乎不是一种合适的方式。

但是,当我们有一个 URLhttp://www.apple.com/index.html 时,我们会得到

绝对字符串:http://www.apple.com/index.html 路径:/index.html

阅读文档在这里也有帮助:

根据 RFC 3986,权限(主机名和端口)部分之后的前导斜杠被视为路径的一部分。

所以path 是在authority 之后的斜线处开始(包括)的所有内容,在我们的例子中是www.apple.com


问题 2

有什么时候应该使用一个而不是另一个?

来自docs:(方法:path

如果此 URL 对象包含文件 URL(由 isFileURL 确定),则此方法的返回值适合输入到 NSFileManager 或 NSPathUtilities 的方法中。

在我看来,这句话清楚地表明当您使用NSFileManagerNSPathUtilities 时应该使用path


结论:

当您使用远程网址时,您(通常)使用absoluteString,否则结果不是您(通常)想要的。 当您使用本地 URL 时,请使用 path

来源:http://www.ietf.org/rfc/rfc1808.txthttp://www.ietf.org/rfc/rfc3986.txtNSURL Class Reference

【讨论】:

谢谢,这是对差异的彻底解释,而不是文档中的 1 句自引用定义。 很确定这一行是错误的:absolute string: file:///Users/dennis/Desktop NSURL 将在创建 URL 时和调用 -absoluteString 时保留准确的字符串,包括尾部斜杠。 @Mike 你完全正确!感谢您的评论,我刚刚编辑了我的答案!当你“玩”得有点多并经常改变事情时就会发生这种情况......再次感谢;) @HAS 似乎文档已更改。它现在说“URL 对象是引用本地文件的首选方式。大多数从文件读取数据或向文件写入数据的 AppKit 对象都有接受 NSURL 对象而不是路径名作为文件引用的方法。”听起来苹果现在通常更喜欢您使用 URL 而不是路径。 这是我第 100 次查找此内容,希望这是我永远记住它的时候……【参考方案2】:

添加到 HAS 的响应中——Apple 文档提到基于路径的 URL 在某些方面更简单,但是文件引用 URL 的优点是,如果在您的应用程序运行时移动或重命名文件,引用仍然有效。

来自“访问文件和目录”的文档:

“基于路径的 URL 更容易操作、更容易调试,并且通常是 NSFileManager 等类的首选。文件引用 URL 的一个优点是,在您的应用程序运行时,它们比基于路径的 URL 更不脆弱。如果用户在 Finder 中移动文件,任何引用该文件的基于路径的 URL 都会立即失效,必须更新到新路径。但是,只要文件移动到同一个磁盘上的另一个位置,它的唯一ID 不会改变,任何文件引用 URL 仍然有效。”

https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html

【讨论】:

【参考方案3】:

进一步说明,我只为 Swift 和URL 尝试过这个,而不是NSURLrelativeTo 形式的 URL:

URL(fileURLWithPath: aPath, relativeTo: URL)

生成一个行为不完全像远程 URL(如上面的@HAS)而不像文件 URL 的 URL。

所以,例如:

let url0 = URL(fileURLWithPath: "/Foo")
let url1 = URL(fileURLWithPath: "Bar", relativeTo: url0)
print("\(url1.path)")
// Output: "/Bar\n"

(类似于远程 URL 的结果,但不是文件 URL)。

如果我们使用absoluteString,我们会得到:

print("\(url1.absoluteString)")
// Output: "file:///Bar\n"

(不类似于文件 URL 或远程 URL)。

【讨论】:

以上是关于NSURL 路径与绝对字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何获取照片库中最新照片的路径? (作为 NSUrl 或字符串)

来自字符串的 NSURL 不起作用

将文件路径转换为文件 url[NSUrl]

字符串与路径

Cocoa 路径字符串转换

从 String 到 NSURL 的转换不断返回 nil