Getting a File Path From a Swift URL

Seth Willits (2024, bug):

There’s a deprecation warning in Xcode for URL.path that reads:
WARNING: path will be deprecated in a future version of macOS: Use path(percentEncoded:) instead
The problem is something like this:
Bundle.main.url(forAuxiliaryExecutable: "tool")!.path
… which returns the expected file path (ex: /Applications/MyApp.app/Contents/tool) would be quickly rewritten as suggested to:
Bundle.main.url(forAuxiliaryExecutable: "tool")!.path(percentEncoded: false)
… which simply returns tool, because the URL returned is relative to a base URL. I’ve always found it not-completely-obvious to newcomers how to get a standard file path string from a file URL and this only makes it more confusing.

There are at least three issues here:

  1. url.path returns an absolute path, but url.path(percentEncoded: false) returned a relative path as of his writing. I tested this on macOS 26, and now it returns an absolute path. The documentation now says, “This function will resolve against the base URL.” It seems the behavior of the method changed without it being documented when, so be careful if you’re deploying to a mix of OS versions.
  2. percentEncoded has a default value of true, whereas path did not return an encoded string. In other words, url.path() and url.path are completely different. So this is another case where Apple updated the API but flipped the default—a good way to introduce bugs.
  3. It’s not obvious how to get the full file system path out of a URL. With NSURL, url.path was natural and did the right thing. Now, the URL equivalent is deprecated. The natural replacement, url.path(), is wrong. So is Xcode’s recommendation of url.(percentEncoded: false). url.absoluteURL.path(percentEncoded: false) is correct but verbose. url.absoluteURL.standardizedFileURL.path(percentEncoded: false) is possibly better but even more verbose. FilePath(url)?.string uses a newer API but gives you an optional, even though for a file URL it should never fail. This seems like such basic functionality, but there’s no API that’s the obvious right choice, concise, and ergonomic.

Previously:

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论