I'm trying to use URLComponents
to compose a URL
as that appears to be what it's for.
However, when I then access the url
property of the components it is nil.
Example...
var urlComponents = URLComponents(string: "http://google.com")!
urlComponents.path = "auth/login"
Then I do ...
print(urlComponents)
Output...
scheme: http host: google.com path: auth/login
- scheme : "http"
- host : "google.com"
- path : "auth/login"
But then...
print(urlComponents.url)
outputs nil
.
Am I doing something wrong with this? How do I get the fully formed URL from all this? Thanks
It looks like
path
parameter's string must start with/
.So change
"auth/login"
to"/auth/login"
will do.TL;DR
If you're creating a web URL (e.g.
http://example.com/path
), include the/
because it uses the following template:If you're creating a non web URL (e.g.
mailto:user@example.com
), don't include the/
because it uses the following template:To clarify why this is happening, the actual template of URLComponents is as follows:
Notice how there is punctuation (
://
,:
,@
,:
,?
,#
) between every two components, except for{port}
and{path}
.Therefore,
{path}
must be prefixed with the punctuation (/
), otherwise it'll produce an invalid URL.In your case you must use :
Note that even if you omit URLComponents's uncommon fields, you still run into the same problem:
Notice how
{host}
and{path}
are adjacent in this case as well, with no punctuation separating the two.You may be wondering why, then, Apple didn't include the punctuation before
{port}
. My guess is because URLComponents can be used to produce any type of URL in the RFC 3986 spec, not only Web URLs. E.g. it could easily producehttp://www.example.com/foo
, but it should just as easily produce a URL of the formmailto:user@example.com
.URLComponents makes this possible by changing the delimiter between
{scheme}
and{path}
when{host}
is omitted:Thus when we want to produce a mailto link, we would actually not include the
/
in path:Comparing the properties of URLComponents to URL's properties provides a bit more insight (and reveals a bit of inconsistency):
Two things to note:
url.path
doesn't have/
in the suffix.url.pathComponents[0]
is the first/
in the URL.For an exhaustive list of templates, you can use this code:
Which produces the following output:
Notice how none of these are
nil
. If you changeurlComponents.path = "/path"
tourlComponents.path = "path"
, however, you get a completely different set of templates: