NSURL path vs absoluteString
Asked Answered
C

3

76

I've seen many questions on SO concerning converting between NSURL and NSString. They all involve using either NSString *path = [myURL absoluteString]; or NSString *path = [myURL path];. What is the actual difference between these methods? Is there a time when one should be used over the other? I tried consulting the Apple Docs, but I found it less than helpful.

I'm used to URL's only being mentioned in discussions concerning websites and other topics regarding sending information between different machines, and never being mentioned when dealing with just the file structure on a single machine. Perhaps this is where some of my confusion is coming from, since NSURL seems to be the preferred way of accessing files, regardless of whether that file exists on a network or on the local device. Or maybe that's a totally unrelated topic. I'm not even sure.

Commensurate answered 23/4, 2013 at 18:46 Comment(3)
I'm surprised the docs were of no help to you, as they are quite explicit as to the use-case of -path. Prefer absoluteString for URLs, if only because of the RFC 1808 resolution algorithm. Prefer -path for file paths because of how strict it is about format, and because the docs mention it is the preferred method for getting a file-manager compatible path.Stomachic
I was going to answer this, but CodaFi beat me to it. CodaFi, I know you don't need the rep, but your comment looks more like an answer to me.Intertidal
possible duplicate of What is difference between URLWithString and fileURLWithPath of NSURL?Parkland
G
168

Question 1:

What is the actual difference between these methods?

Let's analyze this writing 6 lines of code - 3 for a local and 3 for http URL - and playing around with them a little bit.

Let's create an NSURL using the file:// scheme. If you ask yourself why there are 3 / after file: you should remember that a complete URL exists of a scheme (file:// and absolute or relative path (you can find more information on creating URLs in RFC 1808 on page 3). We use an absolute path which starts with a / so that we end up with ///.

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

Output:

absolute string: file:///Users/dennis/Desktop/
path: /Users/dennis/Desktop

So we see that absoluteString still knows its scheme whereas path doesn't have this information anymore.

Note: path is a file (directory) URL and as the docs state, the trailing slash it is stripped.


Now let's take a look at remote URLs. With these type of URLs most people are more familiar. We create it using the same procedure as for local URLs. Our scheme is now http:// and our path is www.apple.com/.

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

Output:

absolute string: http://www.apple.com/
path: /

Again, we see that the absolute string still knows its scheme but path is now /. So path seems to be not an appropriate way when working with remote URLs.

However, when we have an URL like http://www.apple.com/index.html we get

absolute string: http://www.apple.com/index.html
path: /index.html

Reading the docs helps here, too:

Per RFC 3986, the leading slash after the authority (host name and port) portion is treated as part of the path.

So the path is everything beginning (and including) at the slash after the authority which is www.apple.com in our case.


Question 2

Is there a time when one should be used over the other?

From the docs: (method: path)

If this URL object contains a file URL (as determined with isFileURL), the return value of this method is suitable for input into methods of NSFileManager or NSPathUtilities.

In my opinion that sentence states clearly that you should use path when you work with NSFileManager or NSPathUtilities.


Conclusion:

When you work with remote URLs you (generally) use absoluteString, otherwise the result is not what you (generally) want.
When you work with local URLs use path.

Sources:
http://www.ietf.org/rfc/rfc1808.txt
http://www.ietf.org/rfc/rfc3986.txt
NSURL Class Reference

Gloria answered 23/4, 2013 at 20:27 Comment(6)
Thank you, this is a thorough explanation of the difference, instead of the 1 sentence, self referencing definition in the Docs.Commensurate
Pretty sure this line is wrong: absolute string: file:///Users/dennis/Desktop NSURL will preserve the exact string, including trailing slashes, both when creating the URL, and when calling -absoluteStringAculeate
@Mike You are absolutely right! Thanks for your comment, I've just edited my answer! That happens when you "play" a little to much and change things to often ... Thanks again ;)Gloria
@Gloria it seems like the documentation has changed. It now says "URL objects are the preferred way to refer to local files. Most AppKit objects that read data from or write data to a file have methods that accept an NSURL object instead of a pathname as the file reference." Sounds like apple now prefers you to use URLs over paths in general.Redmund
This is the 100th time I've looked this up and hopefully this is the time I'll remember it forever…Zolner
This answer feels like a poem. Well written!!Rogerson
C
0

Adding to HAS' response -- the Apple docs mention that Path-based URLs are simpler in some ways, however file reference URLs have the advantage that the reference remains valid if the file is moved or renamed while your app is running.

From the documentation for "Accessing Files and Directories":

"Path-based URLs are easier to manipulate, easier to debug, and are generally preferred by classes such as NSFileManager. An advantage of file reference URLs is that they are less fragile than path-based URLs while your app is running. If the user moves a file in the Finder, any path-based URLs that refer to the file immediately become invalid and must be updated to the new path. However, as long as the file moved to another location on the same disk, its unique ID does not change and any file reference URLs remain valid."

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

Chiasma answered 13/1, 2018 at 23:40 Comment(0)
F
0

One further note, and I've only tried this for Swift and URL not NSURL. The relativeTo form of URL:

URL(fileURLWithPath: aPath, relativeTo: URL)

generates a URL that behaves not fully like a remote URL (as in @HAS above) and not like a file URL.

So, for example:

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

(similar to results for a remote URL, but not a file URL).

If we use absoluteString, we get:

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

(not similar to either a file URL or a remote URL).

Flitter answered 18/4, 2020 at 18:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.