Prepare String for URL cast in Swift - swift

I have a text Area, the content of which will later be used to create a URL. How can I validate that the url - cast doesn't throw an error? Is there a function that can do that? For example remove all invalid Characters. I cast the String in the following way, but if the user inputs a newline the cast doesn't work:let url: URL = URL(string: urlPath)!

Use optional binding (https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html):
var str = "somescheme://somedata"
if let url = URL(string: str) {
// handle url
} else {
// handle error
}
If you want to strip whitespaces and new line characters, use:
str.trimmingCharacters(in: .whitespacesAndNewlines)

Related

Issue with turning Wikipedia url string into URL in Swift

The URL I am making is valid and will return the desired JSON when testing on Chrome, but fails in my project.
func createWikipediaURL(place: String) -> URL? {
let _place = place.replacingOccurrences(of: " ", with: "%20")
let urlStr =
"https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|pageimages&exintro&explaintext&generator=search&gsrsearch=intitle:\(_place)&gsrlimit=1&redirects=1"
if let url = URL(string:urlStr) {
return url
} else {
return nil
}
}
With the parameter "Malibu Beach" the function will create the proper URL, https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|pageimages&exintro&explaintext&generator=search&gsrsearch=intitle:Malibu%20Beach&gsrlimit=1&redirects=1, but will also result in no URL being returned because this string cannot be casted into a URL. Any suggestions on how to make the string into a URL?
The issue is with the | character in urlStr. I would suggest using Strings addingPercentEncoding method to make the string url safe. Doing so will mean that you won't need to manually replace spaces for place too.
func createWikipediaURL(place: String) -> URL? {
let urlStr = "https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|pageimages&exintro&explaintext&generator=search&gsrsearch=intitle:\(place)&gsrlimit=1&redirects=1"
// Replaces special characters with their percent encoded counter-parts.
guard let escapedUrlStr = urlStr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return nil }
// There's no need for an if statement; URL can be returned as-is.
return URL(string:escapedUrlStr)
}

URL constructor doesn't work with some characters

I'm trying to call a php-script from my app using URLRequest.
The Url path is generated in the String-Variable query and for the request I convert it like this
guard let url = URL(string: query) else {
print("error")
return
}
usually it works, but when the request contains characters like ä, ö, ü, ß the error is triggered. How can I make it work?
The URL(string:) initializer doesn't take care of encoding the String to be a valid URL String, it assumes that the String is already encoded to only contain characters that are valid in a URL. Hence, you have to do the encoding if your String contains non-valid URL characters. You can achieve this by calling String.addingPercentEncoding(withAllowedCharacters:).
let unencodedUrlString = "áűáeqw"
guard let encodedUrlString = unencodedUrlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: encodedUrlString) else { return }
You can change the CharacterSet depending on what part of your URL contains the characters that need encoding, I just used urlQueryAllowed for presentation purposes.
Split your URL in two separate parts:
let baseURLString = "https://www.example.com"
let pathComponent = "áűáeqw"
let fullURL = URL(string: baseURLString)?.appendingPathComponent(pathComponent)

Delete parameter from URL with swift

I have an URL that looks like myapp://jhb/test/deeplink/url?id=4567 .
I want to delete every thing after the ? char. At the end the URL should look like myapp://jhb/test/deeplink/url. how. can I achieve that? convert the url to a string? Regex?
Use URLComponents to separate the different URL parts, manipulate them and then extract the new url:
var components = URLComponents(string: "myapp://jhb/test/deeplink/url?id=4567")!
components.query = nil
print(components.url!)
myapp://jhb/test/deeplink/url
A convenient extension on URL
private extension URL {
var removingQueries: URL {
if var components = URLComponents(string: absoluteString) {
components.query = nil
return components.url ?? self
} else {
return self
}
}
}
can I achieve that? convert the url to a string? Regex?
When working with URLs, it would be better to treat it as URLComponent:
A structure that parses URLs into and constructs URLs from their
constituent parts.
therefore, referring to URLComponent what are you asking is to remove the the query subcomponent from the url:
if var componenets = URLComponents(string: "myapp://jhb/test/deeplink/url?id=4567") {
componenets.query = nil
print(componenets) // myapp://jhb/test/deeplink/url
}
Note that query is an optional string, which means it could be nil (as mentioned in the code snippet, which should leads to your desired output).
You can do like this
let values = utl?.components(separatedBy: "?")[0]
It will break the string with ? and return the array.
The first object of values give you your resultant string.
You can get each URL component separated from URl using
print("\(url.host!)") //Domain name
print("\(url.path)") // Path
print("\(url.query)") // query string

Reading URLS in JSON api with swift

For work we have a third party company which supply a JSON api for some functionality. The JSON contains urls which I try to map in my code with URL(string: ...) but this fails on some urls which have spaces.
For example:
var str = "https://google.com/article/test test.html"
let url = URL(string: str) //nil
Should I ask the third party to encode their URLs ?
Is this normal or should I try to add encoding myself?
Encoding myself is hard I think because the path should be encoded different from the query and the host shouldn't be encoded etc.
Or am I overthinking this?
If the URL contains spaces in its path, escape the characters with addingPercentEncoding(withAllowedCharacters passing the urlPathAllowed character set:
let str = "https://google.com/article/test test.html"
if let escapedString = str.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlPathAllowed),
let url = URL(string:escapedString) {
print(url)
} else {
print("url \(str) could not be encoded")
}
What I would do if I were you, is to split the string up on the space, try converting each of the elements to a url, and when that works save it in your variable.
var str = "https://google.com/article/test test.html"
var url: URL? = nil
for urlString in str.components(separatedBy: .whitespacesAndNewlines) {
let url = URL(string: urlString)
if url != nil {
break
}
}
// url might be nil here, so test for value before using it
If each URL that you get from the API is in the format in your example, you can instead just grab the first element after spitting the string.
var str = "https://google.com/article/test test.html"
if let urlString = str.components(separatedBy: .whitespacesAndNewlines).first {
let url = URL(string: urlString)
}
// url might be nil here, so test for value before using it

Why won't NSURL accept a valid string that contains quotes or braces?

EDIT
https://www.someurl.com/search?&access_token=1,84,848473938;848483,83&_json={"key1":"value1","key2":"value2"}
When declaring a URL that has a JSON string, I obviously need to use braces _json={ } and qoutes \"key1\":\"value1\"
NSURL(string: String), however, magically becomes nil if either of these characters are included in the string.
So as answered correctly here: NSURL is returning nil for a valid URL, I tried using:
let url = NSURL(string: url.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!)
But I believe that's deprecated since it was before Swift 2 was released and I am getting the error: cannot convert value of Type NSCharacterSet to expected argument type NSStringEncoding (aka UInt)
So I tried using
let url = NSURL(string: url.stringByAddingPercentEncodingWithAllowedCharacters(NSUTF8StringEncoding)!)!
and while that did allow NSURL to have a value instead of nil, it did not return the expected results, so something is still wrong.
I know that the format is correct, because if I type the URL string manually in a browser, I get the expected result. If i copy/paste the encoded version from Xcode, it gives me the wrong result as did Swift when encoding as shown above.
Any insight would be much appreciated.
You can modify a mutable character set to remove an allowed character: since you want the commas to be encoded, remove the comma from the URLQueryAllowedCharacterSet before using it.
In Swift 2, we need to dance with NSMutableCharacterSet like this:
let sourceURL = "https://www.someurl.com/search?&access_token=1,84,848473938;848483,83&_json={\"key1\":\"value1\",\"key2\":\"value2\"}"
let charSet = NSMutableCharacterSet()
charSet.formUnionWithCharacterSet(NSCharacterSet.URLQueryAllowedCharacterSet())
charSet.removeCharactersInString(",")
let url = NSURL(string: sourceURL.stringByAddingPercentEncodingWithAllowedCharacters(charSet)!)
print(url!)
Prints:
https://www.someurl.com/search?&access_token=1%2C84%2C848473938;848483%2C83&_json=%7B%22key1%22:%22value1%22%2C%22key2%22:%22value2%22%7D
To do the same thing with Swift 3 we're using the CharacterSet struct instead of NSMutableCharacterSet but it's the same idea:
var charSet = CharacterSet()
charSet.formUnion(.urlQueryAllowed)
charSet.remove(",")
if let encoded = sourceURL.addingPercentEncoding(withAllowedCharacters: charSet) {
if let url = URL(string: encoded) {
print(url)
}
}