0

If I create a URL like this:

    guard var urlComponents = URLComponents(url: "https://example.com/something", resolvingAgainstBaseURL: false) else {
        return
    }

    let queryItems = URLQueryItem(name: "token", value: token)
    urlComponents.queryItems = [queryItems]

    guard let urlWithQueryItem = urlComponents.url else {
        return
    }

I want the end result to be something like https://example.com/something#token=7as78f6asd678768asd768asd678

Instead of the default https://example.com/something?token=7as78f6asd678768asd768asd678

(I'm looking for something smarter than a search and replace of the ? character)

Thanks

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Ghislain Leblanc
  • 194
  • 2
  • 11
  • 1
    Query items are always (per HTTP and URI specifications) separated by '?'. # is used to introduce an anchor into link, but even then it's processed entirely locally and *not* part of the transmitted HTTP request. See this answer: https://stackoverflow.com/a/1637244/3203487. – David Berry Jan 26 '18 at 00:07

2 Answers2

2

As others have noted, URLQueryItem object is more intended for use with querystrings vs anchors/fragments. With that said, below is a function that helps you accomplish what your questions is asking.

func constructURL(withURL urlBase: String, andFragmentFromQueryItem queryItem: URLQueryItem) -> URL?{

guard let url = URL(string:urlBase) else {
    return nil
}

guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
    return nil
}

let fragmentKey = queryItem.name
let fragmentValue = queryItem.value ?? ""

urlComponents.fragment = "\(fragmentKey)=\(fragmentValue)"

guard let urlWithFragment = urlComponents.url else {
    return nil
}

return urlWithFragment

}

let url = constructURL(withURL:"https://example.com/something", 
andFragmentFromQueryItem: URLQueryItem(name: "token", value: "tokenValue"))
let urlString = url?.absoluteString 
print("\(urlString!)")

Here is a link to a working Swift fiddle of the code. http://play.swiftengine.io/code/8JKI3/2

1

As @rmaddy points out, there is a definite difference between the meaning of ? and #. '?' introduces query parameters, which are part of the URL. '#' introduces the "fragment" which is not considered part of the URL.

You can, however use URLComponents to add a fragment to a URL. Just use the fragment property instead:

urlComponents.fragment = "token=\(token)"
David Berry
  • 40,941
  • 12
  • 84
  • 95