Hi,
I have a question regarding how Alamofire works with in progress background transfers.
So, imagine this scenario:
Some questions here:
The question I have with number 3 is if we should be removing the override once all background transfers have completed? What happens if the user starts new ones? In this scenario, it seems like I would be working around Alamofire's code a lot...
Thanks,
Ronak
Hi Ronak,
These are all fantastic questions. At the moment, Alamofire does not have very strong support for background downloads. You observations are all perfectly valid. Let me try to answer your questions one-by-one.
SessionDelegate task closures. When your app gets relaunched, you need to recreate your SessionDelegate and wire up the closures, then recreate the background URL session with the same identifier. This is more or less what you would do if you weren't using Alamofire. What you MUST remember is that you cannot rely on response closures that were attached to a Request. Since your app was terminated and relaunched, the Request objects no longer exist.To use Alamofire with background downloads, you currently need to not use the
responseclosures and override theSessionDelegateclosures.
- You don't need to do this. You only need to recreate your background URL session when your app delegate is notified to
application:handleEventsForBackgroundURLSession:completionHandler:. An easier approach may be to recreate the background URL session when your app is launched. But some people may feel that you should instead create the URL session lazily. Your call either way.
So, in summary, you can absolutely use background URL sessions with Alamofire. There is not as much convenience yet as there could be, but it can certainly be done. You need to make sure you don't use the response closures, and you need to override the task override closures in the SessionDelegate.
_Full Disclosure:_ If you are just downloading files in the background, I'd recommend you just create your own
NSURLSessionandNSURLSessionDelegateand wire it up yourself. The URL requests are easy to build since you really only need to pass a URL. There's just too much overhead on Alamofire for this use case. The Alamofire APIs are also designed around closures chained to theRequestwhich doesn't work with background sessions.
Additionallly, this is already being worked on in #981. I'd encourage you to check it out and provide some feedback. I haven't had time to review that PR yet myself.
Thanks for the awesome question. Hopefully that helps clear some things up. Cheers. 🍻
It looks like you can continue to use the block structure you have now except for two things:
With these changes, people can continue to use the existing set up.
You would query your persistence store to see which downloads are still running, recreate the request objects. The rest runs as it always has.
What do you think?
I don't understand your reasoning here @ronak2121. First off, I don't understand what you mean by multiplexing in #1. As for #2, I don't understand what that accomplishes. Additionally, recreating requests is only easy if you have them completely abstracted and all callbacks are done using a delegate pattern, not closures.
What I mean by multiplexing is that you currently have a dictionary in the SessionDelegate where you map from NSURLSessionTask to Request using the task identifier.
That wouldn't hold up across app restarts since we lose the mapping from a Request Object to its task identifier. It would be better to use the url in that dictionary since the app would know which downloads are still in progress (assuming the app is keeping track in a persistence store of some kind) and can easily recreate the Request objects.
Te second point I was making was there is a slight threading concern with the way the request closures work in that they are dispatched to the set table queue.
The main points I am trying to make here are that I don't think you would have to re-engineer your code so much and tear it all up for this.
Sent from my iPhone
On Feb 9, 2016, at 12:31 AM, Christian Noon [email protected] wrote:
I don't understand your reasoning here @ronak2121. First off, I don't understand what you mean by multiplexing in #1. As for #2, I don't understand what that accomplishes. Additionally, recreating requests is only easy if you have them completely abstracted and all callbacks are done using a delegate pattern, not closures.
―
Reply to this email directly or view it on GitHub.
While I appreciate your feedback here, I respectfully disagree. There are MANY other complex things going on here. As mentioned before, we've put this into our backlog slated for Alamofire 4.0 to make sure we handle things properly. We'll take all this feedback into consideration when we start working through our actual solution.
Cheers. 🍻
OK, had to spend a lot of time googling this to find this thread.
@cnoon any chance some of this information could make it into the documentation somewhere close to the section on background sessions? Currently it doesn't discuss anything about how this is a use-case Alamofire doesn't support directly / well, and it feels like it's something that should be addressed. Recognizing and understanding the complexities involved, so I'm not demanding a fix ASAP, but putting the documentation that this is just something AF cannot do currently would be helpful. I read backwards and forwards over the readme, and it explains how to configure a background session, but never why this isn't a good AF use-case.
Currently it's very easy to wander in, see that AF 'supports' background sessions, and get confused as to how to set it up -- and I could just as easily see someone trying to do it with AF and closures and getting confused by why it's not working at all. I was 'lucky', I realized there was no way at all closures could be restored properly, and started digging in to figure out WTF was going on.
For others who end up here when researching this issue, can @cnoon or anyone confirm whether or not, as of Alamofire 4, the following statement is still accurate? Thanks!
Full Disclosure: If you are just downloading files in the background, I'd recommend you just create your own NSURLSession and NSURLSessionDelegate and wire it up yourself. The URL requests are easy to build since you really only need to pass a URL. There's just too much overhead on Alamofire for this use case. The Alamofire APIs are also designed around closures chained to the Request which doesn't work with background sessions.
It’s still accurate. We hope to create a solution for background transfers that integrates with other Alamofire technologies sometime after Alamofire 5 is out.
Hoping to see it in Alamofire 5 :)
Most helpful comment
It’s still accurate. We hope to create a solution for background transfers that integrates with other Alamofire technologies sometime after Alamofire 5 is out.