How can I get the Data from NSURLSession.sharedSession().dataTaskWithRequest
You can't return data directly from an asynchronous task.
The solution with Swift 2 is to make a completion handler like this:
class PostFOrData {
// the completion closure signature is (NSString) -> ()
func forData(completion: (NSString) -> ()) {
if let url = NSURL(string: "http://210.61.209.194:8088/SmarttvWebServiceTopmsoApi/GetReadlist") {
let request = NSMutableURLRequest( URL: url)
request.HTTPMethod = "POST"
let postString : String = "uid=59"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if let data = data,
jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
where error == nil {
completion(jsonString)
} else {
print("error=\(error!.localizedDescription)")
}
}
task.resume()
}
}
}
let pfd = PostFOrData()
// you call the method with a trailing closure
pfd.forData { jsonString in
// and here you get the "returned" value from the asynchronous task
print(jsonString)
}
That way, the completion is only called when the asynchronous task is completed. It is a way to "return" the data without actually using return
.
Swift 3 version
class PostFOrData {
// the completion closure signature is (String) -> ()
func forData(completion: @escaping (String) -> ()) {
if let url = URL(string: "http://210.61.209.194:8088/SmarttvWebServiceTopmsoApi/GetReadlist") {
var request = URLRequest(url: url)
request.httpMethod = "POST"
let postString : String = "uid=59"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let jsonString = String(data: data, encoding: String.Encoding.utf8), error == nil {
completion(jsonString)
} else {
print("error=\(error!.localizedDescription)")
}
}
task.resume()
}
}
}
let pfd = PostFOrData()
// you call the method with a trailing closure
pfd.forData { jsonString in
// and here you get the "returned" value from the asynchronous task
print(jsonString)
}
NSURLSession.sharedSession().dataTaskWithRequest(request) being executed last
This is simple example how to use completion
:
func authorizeApigee(completion: (auth: Bool) -> Void) {
// Send HTTP GET Request
let scriptUrl = "https://fhirsandbox-prod.apigee.net/oauth/v2"
let urlWithParams = scriptUrl + "/accesstoken?grant_type=client_credentials"
let myUrl = NSURL(string: urlWithParams);
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST"
// Add Basic Authorization
let username = "****"
let password = "****"
let loginString = NSString(format: "%@:%@", username, password)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// Check for error
if error != nil
{
self.errorApigee = 1
print("error=\(error)")
completion(auth: false)
}
// Print out response string
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
completion(auth: true)
}
task.resume()
}
And how to use :
self.authorizeApigee { (auth) -> Void in
if (auth) {
getHealthKitPermission()
} else {
//print errors
}
}
NSURLSession.sharedSession().dataTaskWithRequest runs slow in function
add this on you completionHandler ( it works if you update a view)
dispatch_async(dispatch_get_main_queue(), {
if (error == nil) { ...... }
})
Advice 1:
return the task and use a completion param in your method,
you can cancel the task if it's too slow.
Advice 2 :
Use alamofire and swiftyJson framework
NSURLSession dataTaskWithRequest only works first time
Solved by Changing the cachePolicy
let request = NSMutableURLRequest(URL: NSURL(string: endPoint)!,
cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: Constants.REQUEST.TIMEOUT)
Returning values URLSession.shared.dataTask in swift
You can use completion block to return value. Add completion block your to function like this
func parse (latitude: Double, longtitude: Double, completion: @escaping ((AnyObject) -> Void)){
let jsonUrlString = "https://api.darksky.net/forecast/apiKey/\(latitude),\(longtitude)"
guard let url = URL(string: jsonUrlString) else{
return
}
var information: forecast?
URLSession.shared.dataTask(with: url) { (data, res, err) in
guard let data = data else {
return
}
do {
let json = try JSONDecoder().decode(forecast.self, from: data)
self.info = json
completion(info)
} catch {
print("didnt work")
}
}.resume()
And when you call this function, it return your info
parse( lat, long, {info in
processJson(info)
})
running 2 tasks on one NSURLSession.sharedSession
Here is code sample which makes two requests:
//: Playground - noun: a place where people can play
import UIKit
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let session = NSURLSession.sharedSession()
session.dataTaskWithURL(NSURL(string: "http://www.google.com")!, completionHandler: { (data :NSData?, response :NSURLResponse?, error :NSError?) -> Void in
let res = NSString(data: data!, encoding: NSUTF8StringEncoding)
print(res!)
// make a new request here
let innerSession = NSURLSession.sharedSession()
innerSession.dataTaskWithURL(NSURL(string: "http://www.google.com")!, completionHandler: { (data :NSData?, response :NSURLResponse?, error :NSError?) -> Void in
let res = NSString(data: data!, encoding: NSUTF8StringEncoding)
print(res!)
}).resume()
}).resume()
Get the data from NSURLSession DownloadTaskWithRequest from completion handler
When using download tasks, generally one would simply use the location
provided by the completionHandler
of the download task to simply move the file from its temporary location to a final location of your choosing (e.g. to the Documents or Cache folder) using NSFileManager
.
let task = NSURLSession.sharedSession().downloadTaskWithURL(url) { location, response, error in
guard location != nil && error == nil else {
print(error)
return
}
let fileManager = NSFileManager.defaultManager()
let documents = try! fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
let fileURL = documents.URLByAppendingPathComponent("test.jpg")
do {
try fileManager.moveItemAtURL(location!, toURL: fileURL)
} catch {
print(error)
}
}
task.resume()
You certainly could also load the object into a NSData
using contentsOfURL
. Yes, it works with local resources. And, no, it won't make another request ... if you look at the URL it is a file URL in your local file system. But you lose much of the memory savings of download tasks that way, so you might use a data task if you really wanted to get it into a NSData
. But if you wanted to move it to persistent storage, the above pattern probably makes sense, avoiding using a NSData
object altogether.
Related Topics
Rounding a Double Value to X Number of Decimal Places in Swift
Alternative to Performselector in Swift
Sort Dictionary by Values in Swift
How to Make a Weak Protocol Reference in 'Pure' Swift (Without @Objc)
Can Swift Convert a Class/Struct Data into Dictionary
Difference Between Computed Property and Property Set With Closure
Inout Parameter in Async Callback Does Not Work as Expected
How to Convert Double to Int in Swift
Nsobject Subclass in Swift: Hash VS Hashvalue, Isequal VS ==
How to Generate a Random Number in Swift Without Repeating the Previous Random Number
Nsurlsession Concurrent Requests With Alamofire
Access Firebase Variable Outside Closure
How to Get Current Language Code With Swift
Can You Execute an Applescript Script from a Swift Application