Swift Get Request With Parameters

Swift GET request with parameters

When building a GET request, there is no body to the request, but rather everything goes on the URL. To build a URL (and properly percent escaping it), you can also use URLComponents.

var url = URLComponents(string: "https://www.google.com/search/")!

url.queryItems = [
URLQueryItem(name: "q", value: "War & Peace")
]

The only trick is that most web services need + character percent escaped (because they'll interpret that as a space character as dictated by the application/x-www-form-urlencoded specification). But URLComponents will not percent escape it. Apple contends that + is a valid character in a query and therefore shouldn't be escaped. Technically, they are correct, that it is allowed in a query of a URI, but it has a special meaning in application/x-www-form-urlencoded requests and really should not be passed unescaped.

Apple acknowledges that we have to percent escaping the + characters, but advises that we do it manually:

var url = URLComponents(string: "https://www.wolframalpha.com/input/")!

url.queryItems = [
URLQueryItem(name: "i", value: "1+2")
]

url.percentEncodedQuery = url.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")

This is an inelegant work-around, but it works, and is what Apple advises if your queries may include a + character and you have a server that interprets them as spaces.

So, combining that with your sendRequest routine, you end up with something like:

func sendRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
var components = URLComponents(string: url)!
components.queryItems = parameters.map { (key, value) in
URLQueryItem(name: key, value: value)
}
components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
let request = URLRequest(url: components.url!)

let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard
let data = data, // is there data
let response = response as? HTTPURLResponse, // is there HTTP response
200 ..< 300 ~= response.statusCode, // is statusCode 2XX
error == nil // was there no error
else {
completion(nil, error)
return
}

let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
completion(responseObject, nil)
}
task.resume()
}

And you'd call it like:

sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
guard let responseObject = responseObject, error == nil else {
print(error ?? "Unknown error")
return
}

// use `responseObject` here
}

Personally, I'd use JSONDecoder nowadays and return a custom struct rather than a dictionary, but that's not really relevant here. Hopefully this illustrates the basic idea of how to percent encode the parameters into the URL of a GET request.


See previous revision of this answer for Swift 2 and manual percent escaping renditions.

Swift GET request with url parameters

First off, you're doing a lot more work than is probably necessary. You're encoding your query string parameters into URLComponents which is correct. Then, in your send you are decomposing your URL and parsing out the components then re-encoding them. You're also doing a lot of force-unwrapping, which is fragile and hides problems.

Here's your code simplified in a playground that works for me:

import UIKit
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

let sampleURL = "https://someserver.com/somepath"

func sendRequest(_ url: URL, completion: @escaping ([String: Any]?, Error?) -> Void) {

let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, // is there data
let response = response as? HTTPURLResponse, // is there HTTP response
(200 ..< 300) ~= response.statusCode, // is statusCode 2XX
error == nil else { // was there no error, otherwise ...
completion(nil, error)
return
}
let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
completion(responseObject, nil)
}
task.resume()
}

var urlComponents: URLComponents? {

let resultID = "resultID123"
let resultResponseID = "responseID456"
let questionIndex = "questionNumbers1"

var urlComponents = URLComponents(string: sampleURL)
urlComponents?.queryItems = [
URLQueryItem(name: "surveyResultsId", value: "\(String(describing: resultID))"),
URLQueryItem(name: "surveyResultsResponseId", value: "\(String(describing: resultResponseID))"),
URLQueryItem(name: "questions", value: "\(questionIndex)"),
URLQueryItem(name: "selectedAnswer", value: "\("storedAnswer1")")

]
return urlComponents
}

if let urlComponents = urlComponents, let url = urlComponents.url?.absoluteURL {
sendRequest(url) { (result, error) in
print("Got an answer: \(String(describing: result))")
}
}

When I run this against a server URL that returns valid JSON, I get:

Got an answer: Optional(["image": {
href = "https://example.com";
}, "object_types": {
card = {
fields = {
};
pollable = 1;
};
}])

GET request with parameters

Example how to use URLQueryItem for the requests.

func getRequest(params: [String:String]) {

let urlComp = NSURLComponents(string: "https://my-side.com/data")!

var items = [URLQueryItem]()

for (key,value) in params {
items.append(URLQueryItem(name: key, value: value))
}

items = items.filter{!$0.name.isEmpty}

if !items.isEmpty {
urlComp.queryItems = items
}

var urlRequest = URLRequest(url: urlComp.url!)
urlRequest.httpMethod = "GET"
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)

let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
})
task.resume()
}


getRequest(params: ["token": "AS7F87SAD84889AD"])

(iOS/Swift) Simple GET Request with Path Variables Params

In Params tab, there is 'Path Variable' with an "id" key and a value

This means you can replace this :/id with your actual id value in url.

func getRequestAPICall()  {

let apiUrl : String = "your_server_url" + "/" + "yourIdValueHere"

Alamofire.request(apiUrl, method: .get, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
}
}

How to send Dictionary as parameter to the Get Request Swift

You can use URLComponents for this, URLComponents is defined in Foundation.

        var components = URLComponents()

components.scheme = "http"
components.host = "ctesterst.net"
components.path = "/api/Customers/homeData"

let queryItemLat = URLQueryItem(name: "lat", value: "12.456")
let queryItemLong = URLQueryItem(name: "lng", value: "76.786")
let queryItemAppVersion = URLQueryItem(name: "current_app_version", value: "123")
let queryItemDevice = URLQueryItem(name: "current_device", value: "something")
let queryItemToken = URLQueryItem(name: "access_token", value: "Km3R2AbU0yzAcVkp9BCxmCmaoC5k20fBiQxfLhIBIAolwJGgYw5w5E8X0NZzlDh8")

components.queryItems = [queryItemLat, queryItemLong,queryItemAppVersion,queryItemDevice,queryItemToken]
print(components.url)

Passing an array of parameters as a request body in swift

Try do like this

func marcaAgua(parameters: [String: Any],
completion: @escaping (Result<[MarcaAguaResData], Error>)-> Void) {

let urlString = baseUrl + "events"

guard let url = URL(string: urlString) else {
completion(.failure(NetworkingError.badUrl))
return
}

var request = URLRequest(url: url)
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
request.httpMethod = "POST"
request.setValue("Bearer \(token_login)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

let session = URLSession.shared

let task = session.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
guard let unwrappedResponse = response as? HTTPURLResponse else {
completion(.failure(NetworkingError.badResponse))
return
}

switch unwrappedResponse.statusCode {
case 200 ..< 300:
print("success")
default:
print("failure")
}

if let unwrappedError = error {
completion(.failure(unwrappedError))
return
}

if let unwrappedData = data {
do{
let json = try JSONSerialization.jsonObject(with: unwrappedData, options:.allowFragments)

if let successRes = try? JSONDecoder().decode([MarcaAguaResData].self, from: unwrappedData){
completion(.success(successRes))
}else{

let errorResponse = try JSONDecoder().decode([MarcaAguaErrorResponse].self, from: unwrappedData)
completion(.failure(errorResponse as! Error))
}
}catch{
completion(.failure(error))
}
}
}
}
task.resume()
}


Related Topics



Leave a reply



Submit