Swift URL decoding does not decode string - ios

when trying to decode the following encoded string, it does not work...it´s actually doing nothing...leaving the string as it is:
https://www.foodhat.app/?rOpeningTime=08:00&rClosingTime=20:00&rClosedUntil=2019-08-19&pId=557&rId=69&goTo=CUSTOMER_PRODUCT_DETAILS&cName=Duhok&pName=%D9%85%D9%86%D8%B3%D9%81+%D8%AF%D9%88%D9%84%D9%85%D8%A9&rName=Mansaf+Alzain&rMinOrderValue=15000
pName is arabic, so do not wonder the encoding of it.
I use str.removingPercentEncoding to decode the string...but as said...it doesn´t remove the "+" (e.g. in rName)!
Result is
let str = "https://www.foodhat.app/?rOpeningTime=08:00&rClosingTime=20:00&rClosedUntil=2019-08-19&pId=557&rId=69&goTo=CUSTOMER_PRODUCT_DETAILS&cName=Duhok&pName=%D9%85%D9%86%D8%B3%D9%81+%D8%AF%D9%88%D9%84%D9%85%D8%A9&rName=Mansaf+Alzain&rMinOrderValue=15000"
print(str.removingPercentEncoding!)
//https://www.foodhat.app/?rOpeningTime=08:00&rClosingTime=20:00&rClosedUntil=2019-08-19&pId=557&rId=69&goTo=CUSTOMER_PRODUCT_DETAILS&cName=Duhok&pName=منسف+دولمة&rName=Mansaf+Alzain&rMinOrderValue=15000
What am I doing wrong?

Use 'str.replacingOccurrences()' instead. A better solution would be to use 'URLComponents', 'queryItems' to perform the filtering on the targeted queryItem, to ensure that '+' removal is not done for the entire url.

When decoding an URL you should use URLComponents :
let url = URL(string:"https://www.foodhat.app/?rOpeningTime=08:00&rClosingTime=20:00&rClosedUntil=2019-08-19&pId=557&rId=69&goTo=CUSTOMER_PRODUCT_DETAILS&cName=Duhok&pName=%D9%85%D9%86%D8%B3%D9%81+%D8%AF%D9%88%D9%84%D9%85%D8%A9&rName=Mansaf+Alzain&rMinOrderValue=15000")!
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
print(components)
Output is :
[rOpeningTime=08:00, rClosingTime=20:00, rClosedUntil=2019-08-19, pId=557, rId=69, goTo=CUSTOMER_PRODUCT_DETAILS, cName=Duhok, pName=منسف+دولمة, rName=Mansaf+Alzain, rMinOrderValue=15000]

Related

encode url swift withAllowedCharacters not working encoding %20 as %2520 (means encoding % as %25)

Following is my code for URL encoding
extension String {
var encoded: String {
return self.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
}
}
But I am facing issue if url contains %20. it is encoding it as %2520 although I have added urlQueryAllowed
Original url: https://mydomain.in/retailers_data_v2/retailer/320/17372-Tea%20Coffee%20Vending%20Machine.JPG
Encoded url: https://mydomain.in/retailers_data_v2/retailer/320/17372-Tea%2520Coffee%2520Vending%2520Machine.JPG
If you have an already encoded URL String, you first need to remove percent encoding before applying it again.
If you aren't sure whether the URL you have is already encoded or not, you can simply use an if let on removingPercentEncoding and depending on its result, either call addingPercentEncoding on the original URL or on the one that you removed the encoding from.
let alreadyEncodedURLString = "https://mydomain.in/retailers_data_v2/retailer/320/17372-Tea%20Coffee%20Vending%20Machine.JPG"
if let unencodedURLString = alreadyEncodedURLString.removingPercentEncoding {
unencodedURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
} else {
alreadyEncodedURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
}

Converting string (Contains json string) to NSURL in swift

I have PAI its Implemented in .NET.
one of the web service url is like this
http://123.321.33/UploadCitizenImage?jsonString={\"Mobile\":\"12345678\", \"fileName\":\"7661832460_05072018.png\"}
while converting above string to URL in swift, app going crash.
for more info check this
The URL(string:) initializer returns an optional since the parsing of the string may fail. In that case, nil is returned. That's exactly what's happening here since the string you are providing is not a valid URL: there are several characters in the query that are not allowed there and need to be replaced: { as %7B, " as %22, space as %20 and } as %7D.
So the initializer returns nil. Next thing you do is force unwrap via the ! operator. But force-unwrapping a nil is illegal and is why you get the crash.
If you want to create an URL, please look into the URLComponents class which does all the necessary escaping for you so you don't need to care about it. The queryItems property is of particular interest for you, it's an array of URLQueryItem.
Please do something like that,
let jsonString = "jsonString={\"Mobile\":\"12345678\", \"fileName\":\"7661832460_05072018.png\"}" as String
let urlEncoadedJson = jsonString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)
let urls = NSURL(string:"http://123.321.33/UploadCitizenImage?\(urlEncoadedJson ?? "")")
First convert your json into encodedJson then add into your url.
Do let me know if there is some issue.
You can try this,
let string = "http://123.321.33/UploadCitizenImage?jsonString={\"Mobile\":\"12345678\", \"fileName\":\"7661832460_05072018.png\"}"
let escapedString = string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let url = URL(string: escapedString!)!
print(url)
Output will be like this,
http://123.321.33/UploadCitizenImage?jsonString=%7B%22Mobile%22:%2212345678%22,%20%22fileName%22:%227661832460_05072018.png%22%7D

iOS: Prevent URL from being percent escaped automatically?

I'm fetching some JSON data using URLSession.dataTask. To filter the data, I'm using a parameter that limits by date. The API uses square brackets for this, e.g.
https://foo.com/api/items.json?find[date]=....
However, upon creating a URL with the string and requesting data from it, the square brackets are automatically escaped:
https://foo.com/api/items.json?find%5Bdate%5D=...
With the brackets escaped, the API fails to recognize the request.
I've tried explicitly removing the percent encoding to create a new URL, i.e.
let unsanitized = URL(string: url.absoluteString.removingPercentEncoding)
but the percent sanitization persists.
I've spent a lot of time searching for a solution but haven't had any success—any suggestions?
Per the spec for URI: "A host identified by an Internet Protocol literal address, version 6 [RFC3513] or later, is distinguished by enclosing the IP literal within square brackets ("[" and "]")." rfc3986.
Thus you can't use square brackets for your purpose without escaping them. Your server's REST service is at fault for not handling the escaped characters in the query params. (And I've had situations in recent past where I've had to ask my REST team to fix this sort of problem where they forgot to support escaped query parameter values).
Try use percentEncodedQueryItems of URLComponents instead queryItems.
This is my codes in my app.
let fullUrl = baseURL.appendingPathComponent(path)
guard var components = URLComponents(url: fullUrl, resolvingAgainstBaseURL: false) else {
fatalError("Unable to create URL components")
}
var params = self.parameters // <-- parameters = [String:String]
params["serviceKey"] = Const.OPEN_API_KEY // <-- percent encoded key
components.percentEncodedQueryItems = params.map { // <-- already percent encoded Query Items
URLQueryItem(name: String($0), value: String($1))
}
guard let url = components.url else {
fatalError("Could not get url")
}

Can iOS URL support unicode characters within top level domain?

I'm building an iOS app that takes urls as input.
Unicode characters are valid for a tld but when I instantiate a valid URL that contains unicode characters NSURL returns nil.
Is this even possible?
swift eg.
URL(string: "http://➡.ws/䨹")
How to use special characters in URL (Swift 3) :
let myUrl = "http://➡.ws/䨹" as String
let url = URL(string: myUrl) // nil here .. problem !
if let encoded = myUrl.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed){
let urlencoded = URL(string: encoded) // "http://%E2%9E%A1.ws/%E4%A8%B9" here :) no problem ^^
}

Cyrillic symbols in URL

App crashes with following url:
let jsonUrl = "http://api.com/алматы/events"
let session = NSURLSession.sharedSession()
let shotsUrl = NSURL(string: jsonUrl)
let task = session.dataTaskWithURL(shotsUrl!)
Log:
fatal error: unexpectedly found nil while unwrapping an Optional value
It's because of cyrillic symbols in url. How can I solve this issue. Thanks for your help!
Swift 4
Using String Extension
Create a swift file named String+Extension.swift and paste this code
import UIKit
extension String{
var encodeUrl : String
{
return self.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
}
var decodeUrl : String
{
return self.removingPercentEncoding!
}
}
and Use it like so: (sample according to question):
"http://api.com/алматы/events".encodeUrl
Try this:
let encodedUrl = jsonUrl.stringByAddingPercentEncodingWithAllowedCharacters(URLQueryAllowedCharacterSet)
Something like this:
let apiHost = "http://api.com/"
let apiPath = "алматы/events"
let escapedPath = apiPath.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
let url = NSURL(string: "\(apiHost)\(escapedPath!)")
Obviously you should do something smarter than just force unwrap escapedPath.
Using the Wikipedia page for Swift as an example:
https://ru.wikipedia.org/wiki/Swift_(язык_программирования)
Becomes:
https://ru.wikipedia.org/wiki/Swift_(%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
Which when pasted into the browser takes you to the right page (and most browsers will conveniently render the UFT-8 characters for you).
Non-ASCII characters (and many special characters) need to be escaped in a URL. Chrome and other browser do it automatically. And they unescape the URLs in the address bar for a nicer display.
So if you have a static URL, just paste it into the adressbar, press enter, selected the URL again, copy and paste it to your app:
So instead of:
let jsonUrl = "http://api.com/алматы/events"
You'll get:
let jsonUrl = "http://api.com/%D0%B0%D0%BB%D0%BC%D0%B0%D1%82%D1%8B/events"
Try stringByAddingPercentEncodingWithAllowedCharacters: defined on NSString. You may see people suggesting stringByAddingPercentEscapesUsingEncoding:, but that method is deprecated in iOS 9.
There are also a few predefined NSCharacterSets in Foundation, such as URLHostAllowedCharacterSet and URLPathAllowedCharacterSet. Therefore, if you really have to parse the unescaped URL in code (using preprocessed URLs, mentioned in the accepted answer, is usually a much better idea), you can write a helper method like this:
import Foundation
func url(scheme scheme: String, host: String, path: String) -> NSURL? {
let components = NSURLComponents()
components.scheme = scheme
components.host = host.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
components.path = path.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())
return components.URL
}
// evaluates to http://api.com/%25D0%25B0%25D0%25BB%25D0%25BC%25D0%25B0%25D1%2582%25D1%258B/events
url(scheme: "http", host: "api.com", path: "/алматы/events")
Note that the above documentation mentions that
This method is intended to percent-encode an URL component or subcomponent string, NOT an entire URL string.
That's because according RFC 3986, not all parts of an URL can be percent-encoded (e.g. scheme - http/https/etc.)
in xamarin:
var uri = new Uri (url);
var nsurl = new NSUrl (uri.GetComponents (UriComponents.HttpRequestUrl, UriFormat.UriEscaped));
UIApplication.SharedApplication.OpenUrl (nsurl);
URLs cannot contain Cyrillic characters. There are standards how to translate Cyrillic characters into valid URLs - you might find something if you search for "Punicode" (the P is intentional).

Resources