Returning data from URLSession in Swift - swift

I have tried to research this issue and am unable to find a suitable fix. I attached an image of the code. I am trying to return the subscriptions array which is declared before the URLSession, and data is appended during the URLSession. However, it returns the originally declared, empty array. I added print statements so you can understand what I am talking about. It prints 2 before 1.
let request = NSMutableURLRequest(url: NSURL(string: "https://utelly-tv-shows-and-movies-availability-v1.p.rapidapi.com/lookup?term=\(searchShow)&country=us")! as URL, cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
//let json = try? JSONSerialization.jsonObject(with: data!, options: [])
//print(json)
} else {
//let httpResponse = response as? HTTPURLResponse
let decoder = JSONDecoder()
let json = try! decoder.decode(results.self, from: data!)
//print(json) (for debugging use only)
//print(httpResponse)
for item in json.results{
for each in item.locations{
subscriptions.append(each.display_name)
}
}
//Remove duplicates from array
let uniqueUnordered = Array(Set(subscriptions))
let uniqueOrdered = Array(NSOrderedSet(array: uniqueUnordered))
subscriptions = uniqueOrdered as! [String]
//Print subscriptions array
print("1: \(subscriptions)")
}
})
dataTask.resume()
print("2: \(subscriptions)")
return subscriptions

Related

How to use json response as parameter in another api post call?

I make a GET call and receive a json response. I need to use that json response as one parameter for a subsequent POST call.
I’ve tried to:
-parse the data into an object and pass the [object] as parameter
-parse the data into a string and pass the string as parameter
-parse the data as dict and pass the dict as parameter
but it’s not working, I believe it’s a data thing or a secret I’m missing
How do you use a json response as parameter for a subsequent api call?
//MARK: - PIXLAB facedetect
func facedetectGET(uploadedUrl: String) {
var urlComponents = URLComponents(string: "https://api.pixlab.io/facedetect")
urlComponents?.queryItems = [
URLQueryItem(name: "img", value: uploadedUrl),
URLQueryItem(name: "key", value: Constants.pixlabAPIkey),
]
let url = urlComponents?.url
if let url = url {
// Create URL Request
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 10.0)
request.httpMethod = "GET"
request.addValue("Bearer \(Constants.pixlabAPIkey)", forHTTPHeaderField: "Authorization")
// Get URLSession
let session = URLSession.shared
// Create Data Task
let dataTask = session.dataTask(with: request) { (data, response, error) in
// Check that there isn't an error
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
//make a dict
//let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any]
print("SUCCESS: image detected")
print(json)
//make json a string utf8 so it can be used as parameter in next call
//let jsonString = String(data: json as! Data, encoding: .utf8)
//let jsonData = json.data(using: .utf8)!
//parse json
//decode the json to an array of faces
let faces: [Face] = try! JSONDecoder().decode([Face].self, from: data!)
let facesString = String(faces)
//use dispatch main sync queue??"bottom": Int,
//mogrify call
mogrify(uploadedUrl: uploadedUrl, cord: faces)
}
catch {
print(error)
}
}
}
// Start the Data Task
dataTask.resume()
}
}
//MOGRIFY CALL
func mogrify(uploadedUrl: String, cord: Any) {
let mogrifyurl = URL(string: "https://api.pixlab.io/mogrify")!
//let param: [Face] = result.faces
let param: [String: Any] = ["img": uploadedUrl, "cord": cord]
var request = URLRequest(url: mogrifyurl)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(Constants.pixlabAPIkey)", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = try! JSONSerialization.data(withJSONObject: param, options: [])
URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!)
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!)
print(json)
} catch {
print("error")
}
}.resume()
}
this is how pretty the response looks
enter image description here
and this is how it looks when I pass it as parameter
enter image description here
A POST needs the body as Data. If you're just forwarding the body of the GET to the body of the POST, it would be easiest to leave it as Data.
You could also deserialize the response into an object in your get, and then re-serialize it back into Data in the POST code, but why?
I did lots of white magic, voodoo and lots of praying (aka try and error) and I made it work…
basically decoded the json data, then got an array subdata and encode it back into a data variable as input for the post call
maybe there is an easier and more elegant way but this works....
do {
//decode the json to an array of faces
let cord = try! JSONDecoder().decode(Cord.self, from: data!)
print(cord.faces)
let cordData = try! JSONEncoder().encode(cord.faces)
let coordinates = try JSONSerialization.jsonObject(with: cordData, options: [])
print(coordinates)
//mogrify call
mogrify(uploadedUrl: uploadedUrl, cord: coordinates)
} catch {
print(error)
}
post call
//MOGRIFY CALL
func mogrify(uploadedUrl: String, cord: Any) {
let mogrifyurl = URL(string: "https://api.pixlab.io/mogrify")!
// let param: [Face] = result.faces
let param: [String: Any] = ["img": uploadedUrl, "key": Constants.pixlabAPIkey, "cord": cord]
var request = URLRequest(url: mogrifyurl)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(Constants.pixlabAPIkey)", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = try! JSONSerialization.data(withJSONObject: param, options: [])
URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!)
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!)
print("MOGRIFY response")
print(json)
} catch {
print("error")
}
}.resume()
}

I am doing a post request where I want to type in a question and with the post request get the most common answer

I have done my Post-request but I am unsure about how to make it possible to send a full question and to get the most common answers back to my app.
I am in such a big need of this code in my program so would love to get some examples on how to make it work
Have tried to right the question into the parameters with a "+" instead of space which resulted into nothing.
#IBAction func GetAnswer(_ sender: Any) {
let myUrl = URL(string: "http://www.google.com/search?q=");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"
let postString = questionAsked;
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(String(describing: error))")
return
}
print("response = \(String(describing: response))")
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
let answer = parseJSON[" Answer "] as? String
self.AnswerView.text = ("Anwer: \(String(describing: answer))")
}
} catch {
print(error)
}
}
task.resume()
}
You do not use google.com/search, please check the api documentation
Paste following in Playground, should give a good start
struct Constants {
static let apiKey = "YOUR_API_KEY"
static let bundleId = "YOUR_IOS_APP_BUNDLE_ID"
static let searchEngineId = "YOUR_SEARCH_ENGINE_ID"
}
func googleSearch(term: String, callback:#escaping ([(title: String, url: String)]?) -> Void) {
let urlString = String(format: "https://www.googleapis.com/customsearch/v1?q=%#&cx=%#&key=%#", term, Constants.searchEngineId, Constants.apiKey)
let encodedUrl = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
guard let url = URL(string: encodedUrl ?? urlString) else {
print("invalid url \(urlString)")
return
}
let request = NSMutableURLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10)
request.httpMethod = "GET"
request.setValue(Constants.bundleId, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
let session = URLSession.shared
let datatask = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard
error == nil,
let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : Any]
else {
// error handing here
callback(nil)
return
}
guard let items = json["items"] as? [[String : Any]], items.count > 0 else {
print("no results")
return
}
callback(items.map { ($0["title"] as! String, $0["formattedUrl"] as! String) })
}
datatask.resume()
}
Usage
googleSearch(term: "George Bush") { results in
print(results ?? [])
}
Create a new search engine using following url
https://cse.google.com/cse/create/new
If you would like search entire web, use following steps
edit your engine using https://cse.google.com/cse/setup/basic?cx=SEARCH_ENGINE_ID
remove any pages listed under Sites to search
turn on Search the entire web

How did swift make web requests

I`m a new swifter ,so can take me some help to use swift to make web requests,thanks. Why can't it be reviewed and submitted。
//创建请求体
let param = ["moblie":"18392387159"]
let data = try! JSONSerialization.data(withJSONObject: param, options: JSONSerialization.WritingOptions.prettyPrinted)
var string = "json="
let Str = String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
//拼接
string = string + Str!
let Url = URL.init(string: "http://huixin.smartdot.com:9901/GoComWebService/restful/GoComeRestful/getResetCode")
let request = NSMutableURLRequest.init(url: Url!)
request.timeoutInterval = 30
//请求方式,跟OC一样的
request.httpMethod = "POST"
request.httpBody = string.data(using: String.Encoding.utf8)
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
if (error != nil) {
return
}
else {
//此处是具体的解析,具体请移步下面
let json: Any = try! JSONSerialization.jsonObject(with: data!, options: [])
if let value = JSON(json)["status"].string {
print("状态是:\(value)")
}
print(json)
}
}
dataTask.resume()
i write like this , why it did not work !
I suggest you modify the following code
data is not recommended mandatory unpack ,I am here only to help you find the problem quickly to deal with this problem
do {
let dic = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)
print(dic)
} catch {
print(error)
}
Error returned here is
Error Domain = NSCocoaErrorDomain Code = 3840 "No value." UserInfo = {NSDebugDescription = No value.}
You may ask the parameters of the problem, check their own

swift 3 REST api - get call returns 1 byte instead of 1 (as an int), why?

So I am trying to get a number from my DB. My get call returns 1 when I use postman. However when I run this code underneath, I get 1 byte.
func getDbVersionFromServer(callback: #escaping (_ serverDbVersion: Int16)-> ()) {
let urlPath = "\(baseApiUrl)/users/getDBVersion"
let url = NSURL(string: urlPath)
let session = URLSession.shared
let request = NSMutableURLRequest(url: url as! URL)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
getTokensFromDB(){dbTokens in
request.addValue(dbTokens["accessToken"]!, forHTTPHeaderField: "accessToken")
request.addValue(dbTokens["refreshToken"]!, forHTTPHeaderField: "refreshToken")
request.httpMethod = "GET"
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if let httpResponse = response as? HTTPURLResponse {
if (httpResponse.statusCode == 200){
let aToken = httpResponse.allHeaderFields["accessToken"] as? String
updateAccessTokenOnly(newAccessToken: aToken!)
let dbVersion = data
print("here is data: \(data!) and here is dbVersion \(dbVersion!)")
callback(0)
}
}
})
task.resume()
}
}
What am I doing wrong here? And how do I get my 1? Thanks in advance!
data is type of Data so if your response is not returning JSON you can use String(data:encoding:) to get your expected result.
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if let httpResponse = response as? HTTPURLResponse {
if (httpResponse.statusCode == 200){
let aToken = httpResponse.allHeaderFields["accessToken"] as? String
updateAccessTokenOnly(newAccessToken: aToken!)
if let data = data, let stringResponse = String(data: data, encoding: .utf8) {
print("Response \(stringResponse)")
}
callback(0)
}
}
})
task.resume()

swift URLRequest doesn't send parameters

In the code below
let bodyData = "?sub=\(id)&name=User&email=test#test.com"
let url = NSURL(string: "https://httpbin.org/get");
let request:NSMutableURLRequest = NSMutableURLRequest(url:url as! URL)
request.httpMethod = "GET"
request.httpBody = bodyData.data(using: String.Encoding.utf8);
NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: OperationQueue.main)
{
(response, data, error) in
if let HTTPResponse = response as? HTTPURLResponse {
let statusCode = HTTPResponse.statusCode
if statusCode == 200 {
// Yes, Do something.
let json = try? JSONSerialization.jsonObject(with: data!, options: [])
if let dictionary = json as? [String: Any] {
let args = dictionary["args"]
NSLog("args:\(args)")
for (key, value) in dictionary{
NSLog("key:\(key) value:\(value)")
}
}
}
}
}
id is a string passed in to the function.
It has valid data returned, but the test site/url also returns in json format any parameters you send it. But this snippet of code seems to not be sending the query parameters defined in bodyData and I can't figure out why.
If a GET request is used the parameters are appended to the URL and an explicit URLRequest is not needed at all.
This code is native Swift 3 and uses contemporary API:
let id = 12
let bodyData = "?sub=\(id)&name=User&email=test#test.com"
let url = URL(string: "https://httpbin.org/get" + bodyData)!
URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:Any],
let args = json["args"] as? [String:Any] {
print("args:\(args)")
for (key, value) in args{
print("key:\(key) value:\(value)")
}
}
} catch {
print(error)
}
}.resume()