0

I got problem in that code, I want to send request in background and get an response with confirmation from server that everything - fine.

I need my request to be processed even while user blocks his iPhone. Can someone help? First question: Can that code I wrote work somehow in background mode? Second: If not than can you explain me how can I get an response from server using Delegates and other staff from "NSSessionConfiguration"

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        [self REQUEST_METHOD];
});

1 Answers1

1

You're going down the right road re background NSURLSessionConfiguration. See the sample in https://stackoverflow.com/a/32676536/1271826 for example of how to use delegate based implementation with background sessions.


By the way, as a general observation, when you use NSURLSession, it always runs asynchronously; it never blocks the main thread. It therefore suggests some fundamental misunderstanding when we see NSURLSession code dispatched to a background queue (e.g., in your case, you used a global queue). That dispatch_async is not needed.

Sure, if the the creation of the request is computationally expensive (e.g. you need to compress some video or image assets before sending the request), then, fine, dispatch that to a global queue. But if you’re just creating a simple JSON or x-www-form-urlencoded request, then the dispatch_async to a global queue is not needed. Certainly the NSURLSession doesn’t need it.

So, don't conflate the term “background”. There are three completely different uses of the term:

  1. A “background” GCD queue is one that runs on a thread other than the main thread (e.g., a global queue is type of background queue).

  2. A “background” NSURLSessionConfiguration (or “background session”, in short), is one run by a system daemon, even while your app is not running at all. Your app might not only be suspended, but it might even had been jettisoned during the course of its normal lifespan, but that background session (run by that system daemon) will keep running. (NB: if you force-quit an app, though, the OS interprets that as “the user wants to kill everything associated with that app, including background network requests”, and will stop background NSURLSession requests.)

  3. The “background” execution state of the app, itself, is just one of several possible states/modes that an app can be in. It can be:

    • “active” (running in the foreground);
    • “background” (when the user leaves the app, it resigns its active state and temporarily transitions to running in a “background” mode for a few seconds before it’s suspended; also the OS can sometimes wake a suspended app, let it run something in this background mode, and then suspend the app again);
    • “suspended” (the app is in memory, but is not running at all); and
    • “terminated” (e.g. the app might be jettisoned due to memory pressure, removing it from RAM altogether).

    See About the Background Execution Sequence

So, going back to your question, while the app is active, we create a background session and start a few requests. If the user leaves the app (eventually transitioning the app to a “suspended” state where it’s not running at all), the request on the background session will continue. When the NSURLSession tasks are done, even if the user is using some other app, your app may be started up in the background (no UI shown at all), let the app respond to NSURLSession events (called by those delegate methods) and then the app will be suspended again. And all of this can happen without dispatching anything to a global queue.


Note, while running background NSURLSession isn’t rocket science, it often requires refactoring of our code. You also get dragged into complications. For example, when your app restarts (esp if it had been terminated in this intervening period of time), how do you determine the state of the various network tasks and update your UI accordingly. Also, it’s also tricky because being attached to our debugger can change the app lifecycle, so you need to become familiar with debugging the app when Xcode isn’t running at all. For example, you might use unified messaging and watching the progress on the macOS Console; see Unified Logging and Activity Tracing video and the Unified Logging reference for more information.

So, You might want to ask yourself whether you absolutely need to do all of that. For example, if you think you only need a little time to finish some network request, you might just request that the OS let your app run in the background for a max of 30 seconds after the user leaves the app. See Extending Your App’s Background Execution Time. It’s a lot easier than background NSURLSessionConfiguration.

This background task feature is quite limited (e.g., currently a max of three minutes), but if that’s sufficient for your purposes, it’s a lot simpler.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • I have a loop where im creating request for every item I need to be sent And after first background request everything stops everytime :( – Денис Гавриляк Dec 15 '19 at 17:46
  • I’d suggest you post a separate question with [MCVE](https://stackoverflow.com/help/mcve). But if you’re not starting them before the user leaves the app, but rather are initiating latter ones when the first finishes, then that could make the latter ones run in “discretionary” mode. Or if you violate any of the rules of background execution (e.g., fail to call specified completion handlers of delegate methods within allotted time), your app can be unceremoniously killed. But we’re not going to diagnose this in the comments here, and this really is a separate question. – Rob Dec 15 '19 at 17:53