199

So I have converted an NSURL to a String. So if I println it looks like file:///Users/... etc.

Later I want this back as an NSURL so I try and convert it back as seen below, but I lose two of the forward slashes that appear in the string version above, that in turn breaks the code as the url is invalid.

Why is my conversion back to NSURL removing two forward slashes from the String I give it, and how can I convert back to the NSURL containing three forward slashes?

var urlstring: String = recordingsDictionaryArray[selectedRow]["path"] as String
println("the url string = \(urlstring)")
// looks like file:///Users/........etc
var url = NSURL.fileURLWithPath(urlstring)
println("the url = \(url!)")
// looks like file:/Users/......etc
sudo make install
  • 5,629
  • 3
  • 36
  • 48
Gary Simpson
  • 2,677
  • 2
  • 17
  • 18

10 Answers10

212

In Swift 5, Swift 4 and Swift 3 To convert String to URL:

URL(string: String)

or,

URL.init(string: "yourURLString")

And to convert URL to String:

URL.absoluteString

The one below converts the 'contents' of the url to string

String(contentsOf: URL)
Naishta
  • 11,885
  • 4
  • 72
  • 54
  • 41
    The second part is incorrect. `String(contentsOf: URL)` returns the actual payload of that resource, not the URL in string format. Use `URL.absoluteString` to get the string version of the URL. https://developer.apple.com/reference/foundation/nsurl/1409868-absolutestring – Tomislav Markovski Nov 14 '16 at 13:23
  • 4
    You're making the same mistake as in https://stackoverflow.com/a/39967995/2227743 where you conflate converting the URL itself to a string with converting the downloaded content to a String. You should remove this part of your answer because it is completely wrong (or off-topic, but in the end it's wrong because it doesn't answer the question). – Eric Aya Jan 08 '18 at 11:45
  • 3
    35+ people found this useful and upvoted it, I would rather keep it as is. – Naishta Jan 15 '18 at 11:10
  • 2
    I got burned using `fileManager.fileExists(atPath: dbPath.absoluteString)`, because the conversion from URL preserved the escaped spaces, like this: `Application%20Support` instead of `Application Support`, and it returned false. It didn't do this with `dbPath.path`. Just something to be aware of. – James Toomey Jul 26 '22 at 04:51
128

fileURLWithPath() is used to convert a plain file path (e.g. "/path/to/file") to an URL. Your urlString is a full URL string including the scheme, so you should use

let url = NSURL(string: urlstring)

to convert it back to NSURL. Example:

let urlstring = "file:///Users/Me/Desktop/Doc.txt"
let url = NSURL(string: urlstring)
println("the url = \(url!)")
// the url = file:///Users/Me/Desktop/Doc.txt
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
76

There is a nicer way of getting the string version of the path from the NSURL in Swift:

let path:String = url.path
iphaaw
  • 6,764
  • 11
  • 58
  • 83
  • 9
    but it will return only `/questions/27062454/converting-url-to-string-and-back-again` for url `https://stackoverflow.com/questions/27062454/converting-url-to-string-and-back-again` – Kumar Aug 17 '17 at 08:01
  • 2
    This is actually really useful if you want to use the path for some of the other FileManager methods that need a string path. They don't like the `file://` format. – Ben Baron Mar 26 '19 at 21:16
49

2021 | SWIFT 5.1:

FOR LOCAL PATHS

String --> URL :

let url1 = URL(fileURLWithPath: "//Users/Me/Desktop/Doc.txt")
let url2 = URL(fileURLWithPath: "//Users/Me/Desktop", isDirectory: true)

// !!!!!NEVER DO THIS!!!!!!
let url3 = URL(string: "file:///Users/Me/Desktop/Doc.txt")!
// !!!!!NEVER DO THIS!!!!!!

URL --> String :

let a = String(describing: url1)  // "file:////Users/Me/Desktop/Doc.txt"
let b = "\(url1)"                 // "file:////Users/Me/Desktop/Doc.txt"
let c = url1.absoluteString       // "file:////Users/Me/Desktop/Doc.txt"

// Best solution in most cases
let d = url1.path                 // "/Users/Me/Desktop/Doc.txt"

FOR INTERNET URLs

String --> URL :

let url = URL(string: "https://stackoverflow.com/questions/27062454/converting-url-to-string-and-back-again")!

URL --> String :

url.absoluteString // https://stackoverflow.com/questions/27062454/converting-url-to-string-and-back-again

url.path           // /questions/27062454/converting-url-to-string-and-back-again
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
  • 1
    By the way, the `URL.path` is now deprecated from iOS 16.2 and above. What could be the replacement for it? – Goppinath Feb 09 '23 at 09:21
  • 1
    @Goppinath have no idea, I'm working with macOS =) – Andrew_STOP_RU_WAR_IN_UA Feb 09 '23 at 10:26
  • 1
    _Accessing_ the path is not deprecated - only creating a new URL from a string using _path_ is. – deed02392 Mar 11 '23 at 22:23
  • You don't say WHY to "never" do something. What happens if someone does that? – clearlight May 07 '23 at 22:58
  • 1
    @clearlight because of this initialisation must be used only for internet URLs. If you will use it with local path it can do not work in some cases because of incorrect initialisation. It is for some reason created `init(fileURLWithPath: String)` except `init(string: String)` :) If you want to know details - you always can check official documentation. Also the second one init creates nullable URL this is also bad thing when you are able to init not-nullable URL without loose of anything :) – Andrew_STOP_RU_WAR_IN_UA May 08 '23 at 00:15
  • 1
    @clearlight in my practice some of local URLs created by `init(string:)` just didn't found a file. But the same urls created with correct init found the same file without any problems. – Andrew_STOP_RU_WAR_IN_UA May 08 '23 at 00:19
35

NOTICE: pay attention to the url, it's optional and it can be nil. You can wrap your url in the quote to convert it to a string. You can test it in the playground.
Update for Swift 5, Xcode 11:

import Foundation

let urlString = "http://ifconfig.me"
// string to url
let url = URL(string: urlString)
//url to string
let string = "\(url)"
// if you want the path without `file` schema
// let string = url.path
Roger
  • 973
  • 10
  • 15
  • 1
    It should be noted that this returns also the scheme prefix (think `file:///Users/foo`). While if just the absolute path is needed (think `/Users/foo`), then `url.path` should be used as in @iphaaw's answer below. – Ahmed Khalaf Aug 03 '16 at 13:24
17
let url = URL(string: "URLSTRING HERE")
let anyvar =  String(describing: url)
4b0
  • 21,981
  • 30
  • 95
  • 142
Ahsan
  • 503
  • 4
  • 12
13

Swift 3 (forget about NSURL).

let fileName = "20-01-2017 22:47"
let folderString = "file:///var/mobile/someLongPath"

To make a URL out of a string:

let folder: URL? = Foundation.URL(string: folderString)
// Optional<URL>
//  ▿ some : file:///var/mobile/someLongPath

If we want to add the filename. Note, that appendingPathComponent() adds the percent encoding automatically:

let folderWithFilename: URL? = folder?.appendingPathComponent(fileName)
// Optional<URL>
//  ▿ some : file:///var/mobile/someLongPath/20-01-2017%2022:47

When we want to have String but without the root part (pay attention that percent encoding is removed automatically):

let folderWithFilename: String? = folderWithFilename.path
// ▿ Optional<String>
//  - some : "/var/mobile/someLongPath/20-01-2017 22:47"

If we want to keep the root part we do this (but mind the percent encoding - it is not removed):

let folderWithFilenameAbsoluteString: String? = folderWithFilenameURL.absoluteString
// ▿ Optional<String>
//  - some : "file:///var/mobile/someLongPath/20-01-2017%2022:47"

To manually add the percent encoding for a string:

let folderWithFilenameAndEncoding: String? = folderWithFilename.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
// ▿ Optional<String>
//  - some : "/var/mobile/someLongPath/20-01-2017%2022:47"

To remove the percent encoding:

let folderWithFilenameAbsoluteStringNoEncodig: String? = folderWithFilenameAbsoluteString.removingPercentEncoding
// ▿ Optional<String>
//  - some : "file:///var/mobile/someLongPath/20-01-2017 22:47"

The percent-encoding is important because URLs for network requests need them, while URLs to file system won't always work - it depends on the actual method that uses them. The caveat here is that they may be removed or added automatically, so better debug these conversions carefully.

Vitalii
  • 4,267
  • 1
  • 40
  • 45
8

Swift 3 version code:

let urlString = "file:///Users/Documents/Book/Note.txt"
let pathURL = URL(string: urlString)!
print("the url = " + pathURL.path)
mriaz0011
  • 1,887
  • 23
  • 11
5

Swift 5.

To convert a String to a URL:

let stringToURL = URL(string: "your-string")

To convert a URL to a String:

let urlToString = stringToURL?.absoluteString
andrewlundy
  • 1,073
  • 15
  • 22
1

Swift 3 used with UIWebViewDelegate shouldStartLoadWith

  func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {

    let urlPath: String = (request.url?.absoluteString)!
    print(urlPath)
    if urlPath.characters.last == "#" {
        return false
    }else{
        return true
    }

}
Raj Joshi
  • 2,669
  • 2
  • 30
  • 37