How to send json request to server and not wait on response - django

I am building mobile applications to go with my django based backend. I make a post request in swift like this:
var request: NSMutableURLRequest = NSMutableURLRequest()
var url = "https://webapp.com/makepost/"
url += NSUserDefaults.standardUserDefaults().stringForKey("userPk")!
url += "/"
var err: NSError?
request.URL = NSURL(string: url)
request.HTTPMethod = "POST"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
do {
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(JSONObject, options: NSJSONWritingOptions(rawValue:0))
} catch _ {
print ("error")
}
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) {(response, data, error) -> Void in
var query = String(data: data!, encoding: NSUTF8StringEncoding)
query = query!.stringByReplacingOccurrencesOfString("Optional(", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
query = query!.stringByReplacingOccurrencesOfString(")", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
print(query)
//update ui
}
As soon as I make this post it creates the necessary models in django by reading the jsonObject.
The response doesn't matter and could take long as I'm notifying other users via FCM.
This is what I'm trying to do:
Make a post request.
Ignore the response.
Update the UI immediately after I make the post request.
How should I achieve this?

like so
//set request variable here
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) {(response, data, error) -> Void in
var query = String(data: data!, encoding: NSUTF8StringEncoding)
}
sleep(2)
// wait two seconds for models to create in backend
dispatch_async(dispatch_get_main_queue()) {
self.refresh(self.refreshButton)
//refresh ui here with method that fires another get request
}
}

Related

Rest API Get using swift 3 playground

Please assist in figuring out how do I make REST API GET/POST/DELETE/PUT using swift 3 and in playground.
Examples I got from search don't work as expacted. Also I want to consume Laravel REST API first using GET method.
import Foundation
let headers = ["content-type": "application/json"]
let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:8088/api/person")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
To run asynchronous code in a Playground you have to add these two lines
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
You are mixing up GET and POST semantics.
In a GET request the parameters are included in the URL (http://example.com/api?key1=value1&key2=value2)
In a POST request the parameters are passed in the HTTP body
Note: In Swift 3+ don't use NSURL and NSMutableURLRequest. Use the native API

Upload Stream Requests and UIProgressView, Swift 3

I would like to track the progress of videos uploaded through a stream request with a UIProgressView. Unfortunately, I am not using Alamofire, so I'm not sure if URLSession has this ability. Below is relevant code from my application.
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
let uploadProgress:Float = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
let uploadCell = contentTableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! NewContentCell
uploadCell.uploadProgressView.progress = uploadProgress
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
let uploadCell = contentTableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! NewContentCell
uploadCell.uploadProgressView.progress = 1.0
}
didCompleteWithError correctly sets the UIProgressView to indicate that the upload is complete, however, didSendBodyData is returning values greater than 1 through the uploadProgress calculation.
It's my first time utilizing a stream request, so I'm hoping I simply glossed over something that you could help point out. Here is the structure of my request as well for reference.
let request = NSMutableURLRequest(url: NSURL(string: "\(requestUrl)")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBodyStream = InputStream(data: body as Data)
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
let dataTask = session.uploadTask(withStreamedRequest: request as URLRequest)
dataTask.resume()
Much thanks for your input and help.
Implementing
public func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64)
is the correct way to track stream request progression.
But if you want to now the totalBytesExpectedToSend, you must tell it to the server. So don't forget to set the correct Content-Length header in your request!
Here's the way i'm creating the request:
var request = URLRequest(url: url)
request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
request.addValue(String(dataToUpload.count), forHTTPHeaderField: "Content-Length") // <-- here!
request.httpBodyStream = InputStream(data: dataToUpload)
var task = session.uploadTask(withStreamedRequest: request)
task?.resume()
Reading documentation further, figured out that stream objects do not support totalBytesExpectedToSend. It may be a hack, but just using the file's NSData.length feature allows for correct progress tracking. So for stream requests using URLSession, progress can be tracked by using didSendBodyData, with let uploadProgress: Float = Float(totalBytesSent) / Float(mediaSize), where mediaSize is NSData.length.

Swift 3 >> how to pass data to next view that have been received from HTTP POST Request

please can you explain how to pass the json-data
in "let result" to a new view e.g. a textfield?
Here is the related piece of code:
// make http POST request
let uploadTask = session.uploadTask(with: request as URLRequest, from: body?.data(using: String.Encoding.utf8)!){
(data, response, error) in
(response as? HTTPURLResponse)?.statusCode
// URL Object to String
let result = String(data: data!, encoding: String.Encoding.utf8)
}
uploadTask.resume()

How to set the cookie for a POST Request

We are desperately trying to set a cookie before doing a POST request with Alamofire in Swift3. We only have found solutions for Swift2. Our current code looks like this
Alamofire.request(url, headers: NetworkUtil.getApiKeyHeader())
.responseJSON { response in
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
It's quit simple in the end, if you adapt it from Swift 2
if userCookie != nil, let cookieStorage = Alamofire.SessionManager.default.session.configuration.httpCookieStorage {
cookieStorage.setCookies([userCookie!], for: url, mainDocumentURL: nil)
}

Consume REST web service from Swift client

I built a REST WS using dot net 4.5. When I verified it using the Chrome app Advanced Rest Client I get
request: http://mySite.azurewebsites.net/api/tech
with GET selected
The tool reports a status code of 200 and a JSON response of:
[{"fName":"Fred","lName":"Flintstone"},{"fName":"Barney","lName":"Rubble"}]
Over in XCode, using Swift I try a button that calls hitMyWS():
func hitMyWS(){
var url : String = "http://mySite.azurewebsites.net/api/Tech"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil) {
// process jsonResult
println("it worked")
} else {
// couldn't load JSON, look at error
println("kablooey")
}
}) }
In the console I get "kablooey"
This is my first attempt at REST web services and Swift, please advise.