Converting URL to String and back again - swift

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

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)

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

There is a nicer way of getting the string version of the path from the NSURL in Swift:
let path:String = url.path

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

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

let url = URL(string: "URLSTRING HERE")
let anyvar = String(describing: url)

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.

Swift 3 version code:
let urlString = "file:///Users/Documents/Book/Note.txt"
let pathURL = URL(string: urlString)!
print("the url = " + pathURL.path)

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

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
}
}

Related

let myUrl = URL(string: returns nil in swift

let adr = "http://www.dummy.com/mobil.aspx?id=\(uyeNo)&kaynak=ios\(ulke)&req=DB2021&list=\(liste)"
let encAdr = adr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? ""
let myUrl = URL(string: encAdr)
myUrl is always nil. I couldn't find the reason.
I see String Interpolations in your URL string:
\(uyeNo) \(ulke) \(liste)
Have you assigned values on those three? If not, maybe that's the reason why your myURL value returns fatally nil.
Anyways, if above isn't necessarily your case, you may try the following code that may suit your need:
func myCompleteURL(uyeNo: String,ulke:String,liste: String) -> URL {
let adr = "http://www.dummy.com/mobil.aspx?id=\(uyeNo)&kaynak=ios\(ulke)&req=DB2021&list=\(liste)"
let encAdr = adr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? ""
let myUrl = URL(string: encAdr)
return myUrl!
}
func sampleCallFunction(){
let url = myCompleteURL(uyeNo: "i",ulke: "love",liste: "cats")
print(url)
// Prints: http://www.dummy.com/mobil.aspx?id=i&kaynak=ioslove&req=DB2021&list=cats
}
try! this Updated Answer
let urlString = "http://www.dummy.com/mobil.aspx?id=\(uyeNo)&kaynak=ios\(ulke)&req=DB2021&list=\(liste)"
let urlStringEncoding = urlString.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? ""
guard let url = URL(string: urlStringEncoding) else {
return
}
print(url)

Master Detail app in Swift - how to convert string into URL

I'm new here, so please bear with me. I have a Master-Detail app, and in the DetailViewController.swift file, here's the configureView func where it calls a web view to open a web page.
It's complaining on the let request = URLRequest(url:url) line because url variable is defined as a string. I've tried everything but it won't work.
By the way, MasterViewController.MyVariables.urlString is an array of strings.
func configureView() {
// Update the user interface for the detail item.
if let detail: AnyObject = detailItem {
if let myWebview = webView {
let url = MasterViewController.MyVariables.urlString
let request = URLRequest(url: url)
myWebview.scalesPageToFit = true
myWebview.loadRequest(request)
}
}
}
You can either pass an URL object or create an URL object from the string that you´re passing. Anyhow you need to convert your string into an URL.
if let url = URL(string: MasterViewController.MyVariables.urlString) {
// use url in here
}
Update:
Use this for your example:
if let url = URL(string: MasterViewController.MyVariables.urlString) {
// use url in here
let request = URLRequest(url: url)
}
Update 2:
You have your Struct which is an array of strings. Then you need to do this to get the value you want:
struct MyVariables {
static var urlString: [String]? = ["something"]
}
if let str = MyVariables.urlString?.first, let url = URL(string: str) {
// use url in here
let request = URLRequest(url: url)
print(url)
}
Right now I´m using MyVariables.urlString?.first, in the future if you want another index then you need to get that instead.
This is what I did to make it work:
let stringRepresentation = MasterViewController.MyVariables.urlString?.joined(separator:"")
print ("urlString", MasterViewController.MyVariables.urlString)
print ("sR",stringRepresentation)
let url = NSURL(string: stringRepresentation as! String)
let request = URLRequest(url: url! as URL)
myWebview.scalesPageToFit = true
myWebview.loadRequest(request)

SWIFT: Get path only

I'm searching for a predefined function for getting the path from a path including filename. So instead of getting the filename I want the other part.
Of course I can do it like my own like:
func PathOnly() -> String {
let n = NSURL(fileURLWithPath: self).lastPathComponent?.characters.count
return self.Left(self.characters.count - n!)
}
when extend String, but why reinvent the wheel? :-)
Any idea?
The NSString method stringByDeletingLastPathComponent and the NSURL method
URLByDeletingLastPathComponent do exactly what you want.
Example:
let path = "/foo/bar/file.text"
let dir = (path as NSString).stringByDeletingLastPathComponent
print(dir)
// Output: /foo/bar
let url = NSURL(fileURLWithPath: "/foo/bar/file.text")
let dirUrl = url.URLByDeletingLastPathComponent!
print(dirUrl.path!)
// Output: /foo/bar
Update for Swift 3:
let url = URL(fileURLWithPath: "/foo/bar/file.text")
let dirUrl = url.deletingLastPathComponent()
print(dirUrl.path)
// Output: /foo/bar

Swift Google search with more than two variables

I'm trying to add a google search to my textfield. I've got it so I can look up one or two variables, but after three it crashes. What do I need to change or add to make it work? Here's my code...
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
var urlString: String = textField.text
var url = NSURL(string: urlString)
if (url != nil) {
url = NSURL(string: "http://www.google.com/search?q=\(urlString)")
var request = NSURLRequest(URL: url!)
self.webView.loadRequest(request)
}
if url?.scheme == nil {
var spaces = urlString.rangeOfString(" ")
var urlStrings = urlString.stringByReplacingCharactersInRange(spaces!, withString: "+")
var url = NSURL(string: "http://www.google.com/search?q=\(urlStrings)")
var request = NSURLRequest(URL: url!)
self.webView.loadRequest(request)
}
return false
}
Your spaces = urlString.rangeOfString(" ") is only finding the first space in the string, and so with a string that has more it will only replace the first space with + and none of the others. You need to use something more along the lines of:
urlString = urlString.replacingOccurrences(of: " ", with: "+")
Here we replace every occurence of the " " character with "+". So to summarise:
var urlString: String = textField.text!
urlString = urlString.replacingOccurrences(of: " ", with: "+")
let url = URL(string: "http://www.google.com/search?q=\(urlString)")
let request = URLRequest(url: url!)
webView.load(request)
n.b. I've force unwrapped some things just for example purposes.
You'll also want to make sure that you trim urlString first in order to remove any excess whitespace (e.g double spaces, or spaces at the beginning and end). See here for how to do that!
Update for Swift 5:
var keyword = "Rhinoceros Beetles"
keyword = keyword.replacingOccurrences(of: " ", with: "+")
This should allow you to open the url properly.

Why is RestKit strips my URL, swift?

I am initing my Object Manager:
let baseURL = NSURL(string:"http://xxxxx.net/api")
self.client = AFHTTPClient(baseURL: self.baseURL)
self.objectManager = RKObjectManager(HTTPClient: self.client)
But when I run my code:
objectManager.getObjectsAtPath("/json.product.gf.php", parameters: queryParameters,
success: {(requestOperation, mappingResult) -> Void in
var defaults = NSUserDefaults.standardUserDefaults()
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let d = NSDate()
defaults.setValue(dateFormatter.stringFromDate(d), forKey: "lastProductUpdate")
},
failure: {(requestOperation, mappingResult) -> Void in
NSLog("Failed Products")
})
It errors out because it is stripping "api" from my base url.
Why?
Internally RKObjectManager probably uses init?(string URLString: String, relativeToURL baseURL: NSURL?) to create the new URL from the baseURL and the relative url.
You basically have two problems in your code.
your baseURL does not end in /. The aforementioned API ignores everything behind the last / of the baseURL.
your supposed relative url starts with an /. Which means it's actually an absolute URL. This will ignore everything after the host of the baseURL
The position of the slashes is pretty important if you deal with baseURLs. It's an easy fix:
let baseURL = NSURL(string:"http://xxxxx.net/api/")
and
objectManager.getObjectsAtPath("json.product.gf.php", parameters: queryParameters,
If you have a playground nearby and want to see it yourself:
let baseURL = NSURL(string:"http://xxxxx.net/api")! // http://xxxxx.net/api
let url1 = NSURL(string: "json.php", relativeToURL: baseURL)! // http://xxxxx.net/json.php
let url2 = NSURL(string: "/json.php", relativeToURL: baseURL)! // http://xxxxx.net/json.php
let baseURL2 = NSURL(string:"http://xxxxx.net/api/")! // http://xxxxx.net/api/
let url3 = NSURL(string: "json.php", relativeToURL: baseURL2)! // http://xxxxx.net/api/json.php
let url4 = NSURL(string: "/json.php", relativeToURL: baseURL2)! // http://xxxxx.net/json.php