iOS Swift API URLQueryitem - ios

var urlComponents = URLComponents(string: "https://jsonplaceholder.typicode.com/users/")
urlComponents?.queryItems = [URLQueryItem(name: "id", value: userId.id)]
var urlComponents = URLComponents(string: "https://jsonplaceholder.typicode.com/users/")
urlComponents?.queryItems = [URLQueryItem(name: "id", value: userId.id)]
var urlRequest = URLRequest(url: (urlComponents?.url!)!)
urlRequest.httpMethod = "GET"
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
print("urlRequest=====\(urlRequest)")
session.dataTask(with: urlRequest) { (data, response, error) in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
let userRes = try decoder.decode([UserResponse].self, from: data)
self.delegate?.UserDetailsSuccess(userDetail: userRes)
} catch let error {
print("Error: ", error)
}
}.resume()
I am getting the url as : urlRequest=====https://jsonplaceholder.typicode.com/users/?id=1
The actual url : https://jsonplaceholder.typicode.com/users/1
I need to remove the ?id=
How to remove this characters from this. Please help.
Thanks in advance.

URLQueryItem adds the question mark which represents the query separator.
This REST URL doesn't use URL query so URLQueryItem is not needed at all. Add the user ID with String Interpolation.
URLRequest is not needed either, GET is the default and you don't use a special configuration
let url = URL(string: "https://jsonplaceholder.typicode.com/users/\(userId.id)")!
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error { print(error); return }
do {
let decoder = JSONDecoder()
let userRes = try decoder.decode([UserResponse].self, from: data!)
self.delegate?.UserDetailsSuccess(userDetail: userRes)
} catch {
print("Error: ", error)
}
}.resume()

Related

URLRequest in Swift5

I'm using the OpenWeather Current Weather Data Api, and trying to make a url request to get json data from the api in Swift5. I need to print the json data. Here is some code I found on the internet that I have been trying to use, but has not been working.
Note: I do NOT want to use any external libraries. like alamofire.
let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid={APIKEY}")!
var request = URLRequest(url: url)
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error)
} else if let data = data {
print(data)
} else {
print("nope")
}
}
task.resume()
The Openweathermap API documentation is a bit misleading, the expression {API key} indicates the API key without the braces.
Insert the key with String Interpolation
let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=\(APIKEY)")!
The URLRequest is not needed and dataTask returns either valid data or an error
let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
if let error = error { print(error); return }
print(String(data: data!, encoding: .utf8)!)
}
task.resume()
To display the data create an appropriate model and decode the data with JSONDecoder
So, at first you should be aware that you are registered and already have your own API Key. The main reason that can occur here for not opening link is that You are using a Free subscription and try requesting data available in other subscriptions . And for future if you want to do just get request you don't need to do session.dataTask(with: request), the session.dataTask(with: url) will be OK.)
Here is simpler way of your code.
guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid={APIKEY}") else {return}
let session = URLSession.shared
let task = session.dataTask(with: url) { (data, response, error) in
if let error = error {
print(error)
} else if let data = data {
print(data)
} else {
print("nope")
}
}
task.resume()
Not all APIs work with just URL
So if the API has a header in request, try this code.
Note: The header are dependent on your API.
let semaphore = DispatchSemaphore (value: 0)
let param = [
"language": "english",
"serviceRequestId": 1,
"location": ["latitude": "12.34","longitude": "12.34"]
] as [String : Any]
var request = URLRequest(url: URL(string: "UrlHere")!,timeoutInterval: Double.infinity)
request.addValue("tokenHere", forHTTPHeaderField: "Authorization")
do{
let i = try JSONSerialization.data(withJSONObject: param, options: .prettyPrinted)
// print("\(type(of: i))")
print(String(data: i,
encoding: .ascii) ?? "nil")
request.httpMethod = "POST"
request.httpBody = i
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
semaphore.signal()
do{
let postData = try JSONDecoder().decode(ModelRootClassHere.self, from: data)
print(postData)
MyData = postData
completion()
}
catch{
print(error)
print("error............")
}
}
task.resume()
semaphore.wait()
}catch{
print(error)
}

How to Pass Key Value Parameter in JSON POST method in Swift?

This is API http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/
its parameter: "contactsList" : ["5987606147", "6179987671", "5082508888"]
its header: ["deviceid": "584D97F-761A-4C24-8C4B-C145A8B8BD75", "userType": "personal", "key": "9609cc826b0d472faf9967370c095c21"]
In my code if i put breakpoint then filtertaggedUser() is calling but i am unable to go inside completionHandler the access is not going inside dataTask
Access going to else part why? the api is working.
i am trying to pass parameter key value in URL string like below
let urlStr = "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/?contactsList=" + "8908908900"
is this correct approch?
code for above API:
func filtertaggedUser() {
print("inside filter taggedusers")
let headers = ["deviceid": "584D97F-761A-4C24-8C4B-C145A8B8BD75", "userType": "personal", "key": "9609cc826b0d472faf9967370c095c21"]
let urlStr = "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/?contactsList=" + "8908908900"
let request = NSMutableURLRequest(url: NSURL(string:urlStr)! as URL,cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
// access not coming here
let httpResponse = response as? HTTPURLResponse
if httpResponse!.statusCode == 200 {
print("filter taggedusers inside")
do {
print("filter taggedusers inside do")
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String :AnyObject]
print("filter taggedusers \(jsonObject)")
} catch { print(error.localizedDescription) }
} else { Constants.showAlertView(alertViewTitle: "", Message: "Something went wrong, Please try again", on: self) }
})
dataTask.resume()
}
OUTPUT:
POSTMAN OUTPUT
POSTMAN Body
why response is not coming, where i did mistake, please help me with the code.
We can call the Post request API like below,
func getPostString(params:[String:Any]) -> String
{
var data = [String]()
for(key, value) in params
{
data.append(key + "=\(value)")
}
print(data.map { String($0) }.joined(separator: "&"))
return data.map { String($0) }.joined(separator: "&")
}
func callPostApi(){
let url = URL(string: "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/")
guard let requestUrl = url else { fatalError() }
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
request.setValue("584D97F-761A-4C24-8C4B-C145A8B8BD75", forHTTPHeaderField: "deviceid")
request.setValue("9609cc826b0d472faf9967370c095c21", forHTTPHeaderField: "key")
request.setValue("personal", forHTTPHeaderField: "userType")
let parameters = getPostString(params: ["contactsList":["8908908900"]])
request.httpBody = parameters.data(using: .utf8)
// Perform HTTP Request
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
let httpResponse = response as? HTTPURLResponse
print(httpResponse!.statusCode)
// Check for Error
if let error = error {
print("Error took place \(error)")
return
}
// Convert HTTP Response Data to a String
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString)")
}
}
task.resume()
}
Output :
{"8908908900":{"userId":"9609cc826b0d472faf9967370c095c21","userName":"Satish Madhavarapu","profilePic":null,"oniTaag":true,"tagged":false,"userType":"personal"}}

Why not getting response from one URL?

I am using URLSession. I am not receiving any error or response.
It works with one url. However it does not work with one another.
I have also tried percentencoding. But it doesn't work too.
The code is below
let urlString = "https://stark-spire-93433.herokuapp.com/json"//This is not working
//let urlString = "https://jsonplaceholder.typicode.com/todos"//This is working
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)//URLSession.shared
var request = URLRequest(url: URL(string:urlString)!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: [], options: [])
let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
print("response---",response)
print("error--",error)
if data != nil {
let json = try? JSONSerialization.jsonObject(with: data!)
print("JSOn",json)
} else {
print("error data is nil")
}
})
task.resume()
Too cumbersome code.
This is sufficient
let url = URL(string:"https://stark-spire-93433.herokuapp.com/json")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { print(error!); return }
do {
let json = try JSONSerialization.jsonObject(with: data)
print("JSOn",json)
} catch {
print(error)
}
}
task.resume()

Store JSON data as a variable

I'm trying to figure out how to store JSON data into a variable for later use. How do I store it, and is it possible to use the variable in another view controller, or do I have to do another request to fetch the data?
This is my code:
#IBAction func signinTapped(_ sender: UIButton) {
guard let url = URL(string: "http://XXXXXX/TestReqIOS.php") else {
return
}
let email = txtEmail.text!
let password = txtPassword.text!
let data : Data = "loginSubmit=1&email=\(email)&password=\(password)&grant_type=password".data(using: .utf8)!
var request : URLRequest = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type");
request.setValue(NSLocalizedString("lang", comment: ""), forHTTPHeaderField:"Accept-Language");
request.httpBody = data
print("Calling API")
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// vs let session = URLSession.shared
// make the request
let task = session.dataTask(with: request, completionHandler: {
(data, response, error) in
if let error = error {
print("error")
}
else if let response = response {
print("response")
}
else if let data = data {
print(data)
}
DispatchQueue.main.async { // Correct
guard let responseData = data else {
print("Error: did not receive data")
return
}
print(String(data: responseData, encoding: String.Encoding.utf8) ?? "")
}
})
task.resume()
}
Which will return:
{
"id": "7",
"first_name": "John",
"last_name": "Doe",
"email": "JohnDoe#text.com",
"created": "2019-03-11",
"modified": "2019-03-10",
}
It would be better to use a struct, such as in your case:
struct Data: Codable {
let id: Int
let first_name: String
let last_name: String
let email: String
let created: Date
let modified: Date
}
Then you create a variable of that struct where you will store it:
var dataVariable = [Data]()
Then you can do your URL call like:
func getData(arr: Bool, completion: #escaping (Bool) -> ()) {
let urlJSON = "URL"
guard let url = URL(string: urlJSON) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
let getData = try JSONDecoder().decode([Data].self, from: data)
self.dataVariable = getData
} catch let jsonErr {
print("error serializing json: \(jsonErr)")
}
completion(arr)
}.resume()
}
Then you can access all of this from the dataVariable var. IF you do this in a Manager class you can access it from any ViewController.
To access:
let firstNameString = dataVariable[0].first_name
If there are not multiple trees of the same, then just make sure its:
let getData = try JSONDecoder().decode(Data.self, from: data)
Edit:
In your case put the above here:
let task = session.dataTask(with: request, completionHandler: {
(data, response, error) in
if let error = error {
print("error")
}
else if let response = response {
print("response")
}
else if let data = data {
let getData = try JSONDecoder().decode([Data].self, from: data)
self.dataVariable = getData // <- Just decode here
print(data)
}
DispatchQueue.main.async { // Correct
guard let responseData = data else {
print("Error: did not receive data")
return
}
print(String(data: responseData, encoding: String.Encoding.utf8) ?? "")
}
})
task.resume()

URLSession datatask accessing older version of website?

I am using URLSession to scrape JSON data from my website. My code was throwing various errors relating to casting types, so I added some print statements to my code and found that this function is for some reason accessing an older version of my site. I have since updated the website's data, and verified that the new data is displaying properly both through visiting the website myself and using Rested. However, the print statements in the code below yield old data. The code does not read data from the disk so I am not sure why this is happening.
I have removed the website's link from my code for privacy purposes, but otherwise the function can be found below.
func websiteToDisk() {
let config = URLSessionConfiguration.default
config.waitsForConnectivity = true
let defaultSession = URLSession(configuration: config)
let url = URL(string: someURL)
let task = defaultSession.dataTask(with: url!) { data, response, error in
do {
print("Getting information from website")
if let error = error {
print(error.localizedDescription)
} else if let data = data,
let response = response as? HTTPURLResponse,
response.statusCode == 200 {
//do {
let jsonDecoder = JSONDecoder()
print("about to dcode")
let decodedData = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]//try jsonDecoder.decode([String: [String]].self, from: data)
print(decodedData)
print("accessing dictionary")
print(decodedData!["busLoops"])
let toWrite = decodedData!["busLoops"] as! [String]
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let busLoopsURL = documentDirectoryURL.appendingPathComponent("busLoops").appendingPathExtension("json")
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(toWrite)
try jsonData.write(to: busLoopsURL)
//} catch { print(error)}
}
}
catch { print(error)}
}
task.resume()
}
Try ignore local cache data
guard let url = URL(string: "http://....") else{
return
}
let request = NSMutableURLRequest(url: url)
request.cachePolicy = .reloadIgnoringCacheData
let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, resp, error) in
}
task.resume()

Resources