JennyS
JennyS

Reputation: 119

NSURLSession dataTaskWithURL

I am using NSURLSession dataTaskWithURL:completionHandler. It looks like completionHandler is executed in a thread which is different than the thread(in my case, it's the main thread) which calls dataTaskWithURL. So my question is, since it is asynchronized, is it possible that the main thread exit, but the completionHandler thread is still running since the response has not come back, which is the case I am trying to avoid. If this could happen, how should I solve the problem? BTW, I am building this as a framework, not an application.Thanks.

Upvotes: 0

Views: 744

Answers (3)

Peter Hornsby
Peter Hornsby

Reputation: 4256

In the first part of your question you seem un-sure that the completion handler is running on a different thread. To confirm this let's look at the NSURLSession Class Reference. If we look at the "Creating a Session" section we can see in the description for the following method the answer.

+ sessionWithConfiguration:delegate:delegateQueue:

Swift

init(configuration configuration: NSURLSessionConfiguration,
      delegate delegate: NSURLSessionDelegate?,
 delegateQueue queue: NSOperationQueue?)

Objective-C

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
                                  delegate:(id<NSURLSessionDelegate>)delegate
                             delegateQueue:(NSOperationQueue *)queue

In the parameters table for the NSOperationQueue queue parameter is the following quote.

An operation queue for scheduling the delegate calls and completion handlers. The queue need not be a serial queue. If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.

So we can see the default behavior is to provide a queue whether from the developer or as the default class behavior. Again we can see this in the comments for the method + sessionWithConfiguration:

Discussion

Calling this method is equivalent to calling sessionWithConfiguration:delegate:delegateQueue: with a nil delegate and queue.

If you would like a more information you should read Apple's Concurrency Programming Guide. This is also useful in understanding Apple's approach to threading in general.

So the completion handler from - dataTaskWithURL:completionHandler: is running on a different queue, with queues normally providing their own thread(s). This leads the main component of your question. Can the main thread exit, while the completion handler is still running?

The concise answer is no, but why?

To answer this answer this we again turn to Apple's documentation, to a document that everyone should read early in their app developer career!

The App Programming Guide

The Main Run Loop

An app’s main run loop processes all user-related events. The UIApplication object sets up the main run loop at launch time and uses it to process events and handle updates to view-based interfaces. As the name suggests, the main run loop executes on the app’s main thread. This behavior ensures that user-related events are processed serially in the order in which they were received.

All of the user interact happens on the main thread - no main thread, no main run loop, no app! So the possible condition you question mentions should never exist!

Apple seems more concerned with you doing background work on the main thread. Checkout the section "Move Work off the Main Thread"...

Be sure to limit the type of work you do on the main thread of your app. The main thread is where your app handles touch events and other user input. To ensure that your app is always responsive to the user, you should never use the main thread to perform long-running or potentially unbounded tasks, such as tasks that access the network. Instead, you should always move those tasks onto background threads. The preferred way to do so is to use Grand Central Dispatch (GCD) or NSOperation objects to perform tasks asynchronously.

I know this answer is long winded, but I felt the need to offer insight and detail in answering your question - "the why" is just as important and it was good review :)

Upvotes: 1

Cirec Beback
Cirec Beback

Reputation: 693

I just asked the same question. Then figured out the answer. The thread of the completion handler is setup in the init of the NSURLSession.

From the documentation:

init(configuration configuration: NSURLSessionConfiguration,
     delegate delegate: NSURLSessionDelegate?,
     delegateQueue queue: NSOperationQueue?)`

queue - A queue for scheduling the delegate calls and completion handlers. If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.*

My code that sets up for completion on main thread:

var session = NSURLSession(configuration: configuration, delegate:nil, delegateQueue:NSOperationQueue.mainQueue())

(Shown in Swift, Objective-C the same) Maybe post more code if this does not solve.

Upvotes: 0

Kalaivani
Kalaivani

Reputation: 424

NSURLSessionTasks always run in background by default that's why we have completion handler which can be used when we get response from Web service.

If you don't get any response explore your request URL and whether HTTPHeaderFields are set properly.

Paste your code so that we can help it

Upvotes: 0

Related Questions