URL Object is nil after creating it with let constant string url - swift

Why does the first example give me a nil and the second example give me a valid URL object. I am trying to use this jsonUrlString constant and it's not working.
1)
let jsonUrlString = """
https://myURI.domain.com/
"""
let temp = URL(string: jsonUrlString)
2)
let temp = URL(string: "https://myURI.domain.com/")

The first example has lots of extra spaces in the URL so it's not valid.
It's the same as:
let temp = URL(string: " https://myURI.domain.com/")
It would work if you had:
let jsonUrlString = """
https://myURI.domain.com/
"""
This defines the string without the extra spaces.

Related

Swift Quotation Mark in URL

I'm trying to do a request with Alamofire to this url:
https://overpass-api.de/api/interpreter?data=[out:json];(way[highway~"^(motorway)$"][!maxspeed](around:5,45.792790,3.062686););out%20tags;
but it contains a double quotation mark and the cast into URL fails.
I've escaped the " with the backslash
let urlString = "https://overpass-api.de/api/interpreter?data=[out:json];(way[highway~\"^(motorway)$\"][!maxspeed](around:5,45.792790,3.062686););out%20tags;"
but when I convert the string in a URL, it returns nil
let url = URL(string: urlString)
I've tried replacing the " symbols with %22, but it is still not working. I tried using the addingPercent but it results in a wrong url and returns error 400 or 404
let urlWithEconding = urlString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
I also tried to use AlamoFire method for url casting and encoding, but I cannot make it work...
Here is how you can use URLComponents
let queryValue = "[out:json];(way[highway~\"^(motorway)$\"][!maxspeed](around:5,45.792790,3.062686););out tags;"
var components = URLComponents()
components.scheme = "https"
components.host = "overpass-api.de"
components.path = "/api/interpreter"
components.queryItems = [URLQueryItem(name: "data", value: queryValue)]
If you don't want to escape the quotes you can define the variable like this
let queryValue = """
[out:json];(way[highway~"^(motorway)$"][!maxspeed](around:5,45.792790,3.062686););out tags;
"""

Find a string value on a webpage with swift

I want to pull the balance value from a website: https://nimiq.watch/#NQ74+FLQL+DRE3+99PF+CET0+3N7D+JKLF+MQP6+87KS
The number after hash is the wallet address
I tried to use this to find the balance
wallet_address = "NQ48+8CKH+BA24+2VR3+N249+N8MN+J5XX+74DB+5XJ8"
let myURLString = "https://nimiq.watch/#"+wallet_address
let myURL = NSURL(string: myURLString)
var myHTMLString = try String(contentsOf: myURL! as URL)
print(myHTMLString)
when I inspect element in browser it shows this..
<span>340510.29275 NIM</span>
But when I pull with the script I get this
<span>{%=_formatBalance(Nimiq.Policy.satoshisToCoins(o.balance))%} NIM</span>
any suggestions? or is this just not possible.. thanks!

Insert a character in the filename

I want to insert a suffix in the name of a file (.jpg) I loaded. Say the original filename is "AAA.jpg" and the user specified a suffix like "changed", I want to save in the same folder a new file named "AAA changed.jpg". Here is what I tried:
var noExt = chosenFiles[indexInChoseFiles].deletingPathExtension() // full_path/filename (but PercentEncoding)
let aString=noExt.absoluteString + " " + filenameSuffix + ".jpg" // insert the suffix and the extension
var bString=aString.removingPercentEncoding! // get rid of PercentEncoding
var newPath=URL(string: bString) // *** nil ***
newPath=URL(string: aString) // *** nil ***
aString and bString are OK, but newPath returns nil in both cases.
You almost never should use .absoluteString for the manipulation
of URLs, and removing the percent encoding makes it an invalid
URL string, so that the conversion back to URL fails.
Here is a simplified demonstration of the problem:
let url = URL(fileURLWithPath: "/path/to/my documents/aaa.jpg")
let path = url.absoluteString // "file:///path/to/my%20documents/aaa.jpg"
let path2 = path.removingPercentEncoding! // "file:///path/to/my documents/aaa.jpg"
let url2 = URL(string: path2) // nil
One possible solution is to use .path instead:
let url = URL(fileURLWithPath: "/path/to/my documents/aaa.jpg")
print(url)
// "file:///path/to/my%20documents/aaa.jpg"
let path = url.deletingPathExtension().path
let newPath = path + " CHANGED" + ".jpg"
let newURL = URL(fileURLWithPath: newPath)
print(newURL)
// file:///path/to/my%20documents/aaa%20CHANGED.jpg
Another solution, using only URL methods:
let url = URL(fileURLWithPath: "/path/to/my documents/aaa.jpg")
print(url)
// "file:///path/to/my%20documents/aaa.jpg"
let ext = url.pathExtension // "jpg"
let basename = url.deletingPathExtension().lastPathComponent // "aaa"
let newUrl = url.deletingLastPathComponent()
.appendingPathComponent(basename + " CHANGED")
.appendingPathExtension(ext)
print(newUrl)
// "file:///path/to/my%20documents/aaa%20CHANGED.jpg"

SWIFT URL String build

How do I build the URL as below:
/sap/opu/odata/SAP/ZTM_FOR_MOBILITY_SRV/BusinessPartnerSet('BP-CR-EM01')/?$format=json
I want specifically the part - BusinessPartnerSet('BP-CR-EM01').
BP-CR-EM01 value is dynamic value.
let newUrl = url + "'\(businessPartners[myIndex].partnerId)'"
url has the fixed URL and the + operator followed by dynamic value. Please help me with your suggestions.
I recommend to use URLComponents
var components = URLComponents(string: "http://mycompany.com")!
components.path = "/sap/opu/odata/SAP/ZTM_FOR_MOBILITY_SRV/BusinessPartnerSet('\(businessPartners[myIndex].partnerId)')/"
components.queryItems = [URLQueryItem(name: "$format", value:"json")]
if let url = components.url {
print(url)
// or if you need the string
print(url.absoluteString)
}

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