Swift Encode Custom String to populate URL [duplicate] - ios

This question already has answers here:
Swift - encode URL
(19 answers)
Closed 2 years ago.
I have a URL that takes any String like this:
https://test#api.search?query=\(productSearchString)&limit=1
Now my problem is that this works with for example "iphone" but it crashes with "iphone 12".
I tried encoding it like this:
guard let escapedResourceString = resourceString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else { return }
but this doesn't seem to work in my case because it is returning an incorrect URL that I can not use with my API.
How can I fix this, so the user can type in anything he want but the URL should be created and my API should be able to work with it.
If you need anything more just let me know.

Your parameters needs to be url encoded.
You can use URLComponents to create your URL and pass your parameters as URLQueryItem instances, like that:
let productSearchString = "iphone 12"
var urlComponents = URLComponents(string: "https://test#api.search")
urlComponents?.queryItems = [
URLQueryItem(name: "query", value: productSearchString),
URLQueryItem(name: "limit", value: "1")
]
let url = urlComponents?.url
print(url?.absoluteString ?? "nil") // https://test#api.search?query=iphone%2012&limit=1

Related

getting the output Optional("test") [duplicate]

This question already has answers here:
Unable to remove "Optional" from String
(2 answers)
Closed 2 years ago.
I tried the following code
if let shortURL = shortURL {
var url = "\(shortURL.absoluteString)"
MUser.sharedInstance.setMobileReferralId(url)
self.referralLink.text = url self.copyToClipboard()
}
For the url variable, I get the output Optional("Test"). How do I remove the "Optional" part?
The reason looks like absoluteString is optional so you can provide a default value or using if let to assign its value to url, like below
if let url = shortURL.absoluteString {
print(url)
}
or provide some default blank value like
var url = shortURL.absoluteString ?? ""
print(url)
To remove the Optional part, you only need to unwrap optional right. example:
if let shortURL = shortURL,
let url = shortURL.absoluteString {
print(url)
}

Percent encoding output incorrect in Swift 4 for '(apostrophe) [duplicate]

This question already has answers here:
Swift - encode URL
(19 answers)
Closed 3 years ago.
I am encoding my string to hit a web service. I am using addingPercentEncoding(withAllowedCharacters: CharacterSet) to encode my String.
Everything works fine except the '(apostrophe) character gets encoded to %E2%80%99 instead of %27.
if let _keyword = keyword?
.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
parameters?["keyword"] = _keyword
}
For Example:
When keyword is Maggie's, output = "Maggie%E2%80%99s" instead of "Maggie%27s".
Output is fine for others, when keyword is Jelly Extracts output is "Jelly%20Extracts".
So, how do I encode '(apostrophe) properly to %27
Edit: When I pass static text, like "Maggie's.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)" output is correct but when I wrap it in a variable output comes incorrect.
Instead of urlQueryAllowed use alphanumerics.
let originalString = "Maggie's"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
print(escapedString) // Optional("Maggie%27s")

URLQueryItem value is optional

Hello I am trying to add queryItems to my URLComponents but because URLQueryItem returns its value as an optional the url keeps having a question mark in it.
var params = ["id":"5"]
let queryParams = toStringDictionary(dictionary: params).map { pair in
return URLQueryItem(name: pair.key, value: pair.value)
}
var components = URLComponents(string: fullURL)
components.queryItems = queryParams
print(components.url)//This is the full url https://demo.com/users/?5
//This https://demo.com/users/?5 should be this https://demo.com/users/5
The question mark is of course resulting in a wrong url. I can't get rid of it.
Query parameters are separated from the rest of the url by a question mark, for example:
https://example.com/path?param_name=param_value
The question mark is not due to an optional, but is the way that query params are supplied.
The example in your comment looks like it has lost the name of the param, I would expect it to read
https://demo.com/users/?id=5
If it definitely doesn't include the id= bit, please could you share the implementation of toStringDictionary so that we can see what's going on there? The dictionary you pass in is already a string dictionary, so seems odd to have such a function.
EDIT: following your clarifications (which have now disappeared, but made it clear that you were looking to add to the path rather than the query string)
It looks like your code is adding query parameters correctly; look closer at the URL it produces, it will be https://demo.com/users/?id=5. Query parameters are not part of the path, they come at the end and are separated from the rest of the URL by a ?
From your edits, it looks as though what you actually want to do is to add to the path of the URL, so that you get https://demo.com/users/5. That URL does not have any query parameters, so URLQueryItem is the wrong tool for the job.
To add to the path, you can do something like the following:
let userID = "5"
let url = URL(string: "https://example.com/users")!
let newUrl = url.appendingPathComponent(userID)
print(newUrl.absoluteString) //https://example.com/users/5
NB - url is only force unwrapped for brevity in the example, since the string passed to URL() is known to be valid. In real use, you should treat the optional more carefully.
There's something wrong with your toStringDictionary
Assuming
let fullURL = "https://demo.com/users/"
all you need to do is…
let queryParams = params.map{ URLQueryItem(name: $0, value: $1) }
var components = URLComponents(string: fullURL)!
components.queryItems = queryParams
print(components.url!)
// https://demo.com/users/?id=5
Note that you should avoid the force unwrapping in practice

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

What is the function of URLQueryItem in swift?

I am a beginner in iOS development, recently I am learning about networking with rest API in iOS development. When constructing URL to make request, I found code like this:
var queryComponents: [URLQueryItem] {
var components = [URLQueryItem]()
for (key, value) in parameters {
let queryItem = URLQueryItem(name: key, value: "\(value)")
components.append(queryItem)
}
return components
}
I don't understand why the array component shall be in URLQueryItem data type.
Thanks in advance :)
Actually in URLComponents has a property called queryItems which requires array of URLQueryItem, Its purpose is to add number of parameters in the API request
In your case why they would have implemented queryComponents as an array is that they would have been assigning multiple URLQueryItems for a request in queryComponents.
Eg:
queryComponents.append(NEW_URLQueryItem1)
queryComponents.append(NEW_URLQueryItem2)
And finally when we access queryComponents we will get array value which we can directly assign to URLComponents as follows,
var urlComponents = URLComponents(string: "API_URL")
urlComponents.queryItems = queryComponents

Resources