I have a function which posts a dictionary back to the server and return the status code or error content when there's an error. It works fine sometimes, while the rest of the time the completion section is skipped.
func postData(url: String, query: NSDictionary) ->NSObject? {
var error: NSError?
var result: NSObject? = nil
let dest = NSURL("http://myUrl.com")
let request = NSMutableURLRequest(URL: dest!)
request.HTTPMethod = "POST"
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(query, options: NSJSONWritingOptions.allZeros, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
data, response, error in
if(error != nil){
println(error)
result = error
return
}
result = (response as! NSHTTPURLResponse).statusCode
return
}
task.resume()
return result
}
I referred to NSURLSession dataTaskWithRequest not being called, and knew that it may caused by executing time lag. However, since I need the status code (which returns nil so far) to determine the actions to do after the post, I'm wondering how I could solve this problem?
Your method is async method,you can not get return from this.
You can pass in a block to handle your action with return
func postData(url: String, query: NSDictionary,finished:(NSObject)->()) {
var error: NSError?
var result: NSObject? = nil
let dest = NSURL("http://myUrl.com")
let request = NSMutableURLRequest(URL: dest!)
request.HTTPMethod = "POST"
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(query, options: NSJSONWritingOptions.allZeros, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
data, response, error in
if(error != nil){
println(error)
result = error
return
}
finished((response as! NSHTTPURLResponse).statusCode)
}
task.resume()
}
Then use it
postData(url, dic) { (object:NSObject) -> () in{
//use here
}
Related
Hi guys below is my code im using at the moment im making a pos system and talk to a merchant and return talks to a pin pad .
the problem i have is that when i do a purchase for the first time it works 100 percent i get a response from the service
. but when i do another purchase and it does the call nothing happens .
im wondering if the task inst done yet . i dont know whats going on any help
only way i can do another call is by restarting the app
func pinPad(Total:Int,echoData:Int64,retrievalReferenceNumber:Int64, cardAcceptorTerminalId:Int64,cardAcceptorIdCode:Int64) -> String
{
getdata()
var status:String = ""
let Message = "<?xml version='1.0' encoding='utf-8'?>"
var is_URL: String = "http://\(ipcon):\(portcon)/merchant/service"
var session = URLSession.shared
var lobj_Request = NSMutableURLRequest(url: NSURL(string: is_URL)! as URL)
var task: URLSessionTask? = nil
var err: NSError?
lobj_Request.httpMethod = "POST"
lobj_Request.httpBody = Message.data(using: String.Encoding.utf8)
lobj_Request.addValue("http://\(ipcon):\(portcon)", forHTTPHeaderField: "Host")
lobj_Request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
// lobj_Request.addValue(String(count(Message)), forHTTPHeaderField: "Content-Length")
//lobj_Request.addValue("223", forHTTPHeaderField: "Content-Length")
lobj_Request.addValue("http://\(ipcon):\(portcon)/merchant/service", forHTTPHeaderField: "SOAPAction")
print("helo: \(lobj_Request)")
if nil != task{
task!.cancel()
task = nil
}
let sem = DispatchSemaphore(value: 0)
task = session.dataTask(with: lobj_Request as URLRequest){ data, response, error in
if error != nil{
return
}else{
let strData = NSString(data: (data)!, encoding: String.Encoding.utf8.rawValue) as! String
print("Body: \(strData)")
let xml = SWXMLHash.config {
config in
config.shouldProcessLazily = true
}.parse(strData)
if(xml["S:Envelope"]["S:Body"]["responseCode"].element?.text != nil)
{
status = xml["S:Envelope"]["S:Body"]["responseCode"].element!.text
}
else{
status = xml["S:Envelope"]["S:Body"]["ns2:responseCode"].element!.text
}
sem.signal()
}
}
task?.resume()
sem.wait()
session.invalidateAndCancel()
return status
}
Im trying to post a http request with parameters, the response is XML Formatted.
see: https://www.codepunker.com/tools/http-requests/64243-brrjq9t
now, when I try to code that im always getting the same error 500. what I do wrong?
guard let url = URL(string: "http://www.nakdan.com/GetResult.aspx") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
var bodyData = "txt=מה קורה&usr=&pass=&ktivmale=false"
request.httpBody = bodyData.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request as URLRequest){
data,response, error in
print(response!)
if error != nil{
print("error")
return
}
}
task.resume()
Question I want to get the value returned from my ApiToken function so I can use it in another function. For some reason I can not get the value from this function it will not return anything. How could I return the value from my ApiToken function and use it in another function.
Here is my GetApiToken class with the ApiToken function
class GetApiToken {
public func ApiToken(link: String, completionBlock: #escaping (String) -> Void) -> Void
{
let url = URL(string: link)!
let jsonDict = ["username": "snow", "password": "ssssssssss"]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonDict, options: [])
var request = URLRequest(url: url)
request.httpMethod = "post"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
print("error:", error)
return
}
do {
guard let data = data else { return }
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] else { return }
//self.token = json["access_token"] as? String ?? "x"
completionBlock((json["access_token"] as? String)!)
} catch {
print("error:", error)
}
}
task.resume()
}
}
Here is where I am trying to get the value
func getData(_ link:String)
{
let url = URL(string: link)!
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20)
request.httpMethod = "GET"
var output = ""
GetApiToken().ApiToken(link: "http://localhost:5000/auth", completionBlock: { str in
output = str
})
request.addValue("JWT \(output)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type") ..........
It's an asynchronous call, so you need to put everything that will happen once the data has been retrieved in the completion callback
func getData(_ link:String)
{
let url = URL(string: link)!
var request = URLRequest(url: url,
cachePolicy: .reloadIgnoringCacheData,
timeoutInterval: 20)
request.httpMethod = "GET"
GetApiToken().ApiToken(link: "http://localhost:5000/auth",
completionBlock:
{ output in
request.addValue("JWT \(output)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
.......
})
The method fails to return a value got from a GET request where variable res can be printed in the task section, but fails to return it in the end.
func lookUpTheWord(word:String) -> NSDictionary {
var res = NSDictionary()
let urlString = "https://wordsapiv1.p.mashape.com/words/" + word
if let url = NSURL(string:urlString) {
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
request.addValue("this is a key", forHTTPHeaderField: "X-Mashape-Key")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("\(error)")
return
}
res = self.toJson(data!)
print(res) //it works here
}
task.resume()
}
return res //res becomes nil
}
That is because you're returning the variable res before it has been assigned. You'll notice that the res that isn't nil is printed after the one that is after it. This is because the HTTP request doesn't happen instantly - code after it is executed before it is finished, therefore it is called "asynchronous".
If you want to use the variable acquired in the HTTP request, use a closure as a parameter in your function and call it when the request is finished. Example:
func lookUpTheWord(word:String, completion: (NSDictionary->Void)) {
var res = NSDictionary()
let urlString = "https://wordsapiv1.p.mashape.com/words/" + word
if let url = NSURL(string:urlString) {
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
request.addValue("this is a key", forHTTPHeaderField: "X-Mashape-Key")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
res = self.toJson(data!)
completion(res)
}
}
task.resume()
}
}
Used like this:
lookUpTheWord("word") { res in
print(res)
}
Im attemping to make a HTTPRequest using NSURLSession. When I set the full url the request returns the correct data but when using parameters (NSJSONSerialization.dataWithJSONObject -> HTTPBody I get this error
error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
is there something im doing wrong here?
let json = ["api_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted)
let url = NSURL(string: "https://api.themoviedb.org/3/discover/movie")!
let request = NSMutableURLRequest(URL: url)
request.HTTPBody = jsonData
request.HTTPMethod = "GET"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
if error != nil{
print("Error -> \(error)")
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject]
print("Result -> \(result)")
} catch {
print("Error -> \(error)")
}
}
task.resume()
} catch {
print(error)
}
}
This is not a duplicate! I looked at the suggested answer (none of them worked) before asking this question
In your case that issue can be solved by changing the request.HTTPMethod = "GET" to request.HTTPMethod = "POST"
You should not send HTTP Body in the get request, to send the data with the body you should change HTTPMethod to post
Note: Please check if this api method supports POST requests, if it don't support post you can't use it with http body/post, as per doc i only find 'get' request for the discover/movie which can be like this:
let url = NSURL(string: "http://api.themoviedb.org/3/discover/movie?api_key=YOUR_API_KEY")!
let request = NSMutableURLRequest(URL: url)
request.addValue("application/json", forHTTPHeaderField: "Accept")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { data, response, error in
if let response = response, data = data {
print(response)
print(String(data: data, encoding: NSUTF8StringEncoding))
} else {
print(error)
}
}
task.resume()
Ref: You can check more information from this url: http://docs.themoviedb.apiary.io/#reference/discover/discovermovie/get