NSURLSession.dataTaskWithRequest is not working
You have forget to resume()
the task. Please find the below edited code of your's!
static func LoadJsonFromNetwork(url:NSURL, completion:((NSDictionary) -> ())) {
print("Creating request")
let urlRequest = NSMutableURLRequest(URL: url, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 15.0)
print("Creating session")
let session = NSURLSession.sharedSession()
print("Send request")
let task = session.dataTaskWithRequest(urlRequest) {
(data: NSData?, response: NSURLResponse?, error: NSError?) in
print("Checking error and nil data")
if (error == nil && data != nil) {
print("Request json dictionary from nsdata")
if let result = self.NSDataToJson(data!) {
print("Dispatching to main queue")
dispatch_async(dispatch_get_main_queue()) {
print("Calling callback")
completion(result)
}
}
} else {
print(error!.description)
}
}
task.resume() //you need to call this
}
NSURLSession dataTaskWithRequest not being called
The problem that you are facing is that dataTaskWithRequest is an asynchronous call, that's the reason why you receive an empty array (that's only chance that finish and return a the same time and sometimes you receive data).
For that, you need to use a closure that get's call from the closure of dataTaskWithRequests.
Like this (here I only show you the declaration method with a closure):
func getDates (success:([NSDate])->Void){
And in the body of your network call:
var task = sessionDays.dataTaskWithRequest(requestDays, completionHandler: {data, response, error -> Void in
// Convert into array of NSDate objects
var yourArrayOfNSDateConverted:[NSDate] = [NSDate]()
success(yourArrayOfNSDateConverted)
})
Obviously the yourArrayOfNSDateConverted contains your process the data and also you need to manage the error (for that you can add another closure).
NSURLSession dataTaskWithRequest only works first time
Solved by Changing the cachePolicy
let request = NSMutableURLRequest(URL: NSURL(string: endPoint)!,
cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: Constants.REQUEST.TIMEOUT)
NSURLSession: method dataTaskWithRequest never reach completion callback on lengthy responses
When fetching large resources, you should use download task. A data task will attempt to load the entire response in a single NSData
object. Loading a large asset in memory at the same time is not only inefficient, but if it is extraordinarily large, can cause problems.
A download task is well suited for these tasks, because it will stream the asset to a temporary file for you, reducing the peak memory usage. (Admittedly, you can manually achieve the same with data task with delegate pattern, but download tasks do this for you.)
You said:
I saw that there's an alternative method in
NSURLSession
dedicated for downloading files calleddownloadTaskWithRequest
but it doesn't have an async completion block.
Two observations:
There is a rendition,
dataTaskWithRequest:completionHandler:
, that has a completion block:NSURLSession* session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
...
}];
[task resume];Note, I would advise using
sharedSession
if you are not setting a delegate, or otherwise customizing yourNSURLSession
. You do not want to instantiateNSURLSession
objects unnecessarily. And if you really must instantiate aNSURLSession
, re-use it for subsequent tasks and/or make sure to callfinishTasksAndInvalidate
after submitting the last task for that session, or else theNSURLSession
will leak. And, if you instantiate your ownNSURLSession
, you do not have to instantiate your own operation queue, as it will, by default, create a serial queue for you if you do not supply an operation queue.The rendition without a block parameter,
downloadTaskWithURL:
, works, too. All you need to do is to specify adelegate
for yourNSURLSession
and then and implementURLSession:downloadTask:didFinishDownloadingToURL:
.The reason I suggest this is that, often, when we are downloading very large assets (especially over cellular), we realize that the users may want to leave our app and let the download complete in the background. In those situations, we would use a background
NSURLSessionConfiguration
. And when using background sessions, you must use this delegate-based approach. So, if you think you might eventually adopt background sessions for long downloads, then adopting a delegate-based approach now is not a bad idea.For more information, see Downloading Files in the Background.
NSURLSession completion block not called
So I tried calling it like this
session.dataTaskWithRequest(urlRequest,
completionHandler: {(data: NSData!,
response: NSURLResponse!,
error: NSError!) in
print(data)
print(response)
print(error)
}).resume()
And it worked.
Seems like I have to call resume()
on a default suspended session task.
Related Topics
Use Huge Numbers in Apple Swift
Swiftui How to Programatically Adjust Spacing Between Images and Text
Image Disappears When Styling Class to Make a Round Image
How to Display an Image by an API Url? Swift
Can Openssl Be Bundled for Wget Wrapper App to Reference in Xcode Project
Why Does Classa Adopting Protocolb Not Satisfy the Protocolb Requirement
Disable Email Detection in Swiftui's Text
Replacing Multiple Different Occurences with Multiple Different Replacements - Swift4.2
Swift: Can't Edit Properties of Custom Table Cell Programmatically
Comparing Objects in an Array Extension Causing Error in Swift
Can't Use 'Shape' as Type in Swiftui
How to Handle Unsafepointer<Unmanaged<Cfarray>>
What Does Cloning a Github Repository Mean
How to Run the Simulator the Operation Couldn't Be Completed. (Launchserviceserror Error 0.)