NSURLSessionDataTask dataTaskWithURL completion handler not getting called
If you're going to use the completion block rendition of the data task, rather than specifying a delegate
of nil
, like this:
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject
delegate: nil
delegateQueue: [NSOperationQueue mainQueue]];
You should instead instantiate your session using the method that does not take a delegate
at all:
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject];
Or, alternatively, given that you're not customizing your configuration at all, you can skip the instantiation of the NSURLSessionConfiguration
altogether and use the shared NSURLSession
:
NSURLSession *defaultSession = [NSURLSession sharedSession];
But, bottom line, you should not use the sessionWithConfiguration:delegate:queue:
rendition unless you're going to implement the delegates, in which case you wouldn't use the rendition of the NSURLSessionDataTask
method with the completionHandler
parameter.
Also, make sure your device/simulator is running iOS 7.0 or greater.
NSURLSessionDataTask completion handler not executing in command line project
A command line interface does not have a runloop by default so asynchronous tasks cannot work.
You have to start and stop the runloop explicitly
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
CFRunLoopRef runloop = CFRunLoopGetCurrent();
NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@", json);
CFRunLoopStop(runloop);
}];
[dataTask resume];
CFRunLoopRun();
}
return 0;
}
You should handle the dataTask
error to exit with a value != 0
Why doesn't NSURLSession.dataTaskWithURL() call my completion handler?
You forgot to call resume()
.
let session:NSURLSession = NSURLSession(configuration: sessionConfig)
let task = session.dataTaskWithURL(actualUrl, completionHandler: {
(data:NSData?, response:NSURLResponse?, error:NSError?) in
NSLog("Got data = \(data)")
NSLog("Got response = \(response)")
NSLog("Got error = \(error)")
self.searchResults = data
self.delegate?.searchResultsAreReady()
})
task.resume() // you miss this
NSURLSessionDataTask not executing the completion handler block
NSURLSessionDataTask
runs in a background thread. To update anything in the user interface such as labels, buttons, table views, etc, you must do so on the main thread. If you want to update the label text from the completionHandler
block then you need to update the label in the main thread like so:
dispatch_sync(dispatch_get_main_queue(), ^{
nameLabel.text = @"yay!";
});
session.dataTaskWithURL completionHandler never called
The task never completes because it never gets started. You have to manually start the data task using its resume()
method.
let urlPath = apiURL + apiVersion + url + "?api_key=" + apiKey
let url = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { data, response, error in
print("Task completed")
// rest of the function...
}
task.resume()
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.
NSURLSessionDataTask wait completion failed
You have specified your delegate queue to be the main queue. But you have blocked the main thread with dispatch_semaphore_wait
. This is a classical deadlock, waiting for code to run on a queue which is blocked.
You could specify nil
for your session’s delegate queue, and then you wouldn't deadlock. Or use [NSURLSession sharedSession]
.
I would also encourage you to consider eliminating the semaphores entirely. I understand the appeal of semaphores, but it is almost always the wrong solution. Apple removed synchronous networking API for a reason. The semaphore trick feels like an intuitive work-around, but it is inefficient, leads to substandard UX, and can even cause your app to be terminated by the watchdog process in certain situations.
Related Topics
Could Not Cast Value of Type 'Uitableviewcell' to '(Appname).(Customcellname)'
The Sandbox Is Not in Sync with the Podfile.Lock-Ios
Ios: One Ibaction for Multiple Buttons
Get Instance of Viewcontroller from Appdelegate in Swift
Cannot Import Firebase into Swift Class
How to Add Text Using Paths Drawing
How to Disable iPhone 6 Native Resolution
Fcm Push Notifications Do Not Work on iOS 11
Urlresponse Is Not Retrieved After Storing in Cache Using Storecachedresponse
Make Timer Run on Background iOS for More Than 3 Minutes
Swift UI Remove Extra List Empty Cells Without Navigation Controller
Uiactionsheet Cancel Button Strange Behaviour
How to Set Cornerradius for Only Bottom-Left,Bottom-Right and Top-Left Corner of a Uiview