Share extension: proper way to handle background transfers

What is the official flow for handling background transfer events in share extension?

Documentation clearly states that "lengthy" operations should not be performed in foreground, so we're required to "complete request" (dismissing the extension UI) before file upload is over. Thing is, no matter how i try, NSURLSession events are delivered to extension process, rather that containing app (unless i kill extension process with exit(0)). Problem is, transfer may fail, and there's no way to notify user: UI is dismissed, notifications are not avalable, containing app couldn't be called, etc.
So, I wonder, am I doing something wrong? What is the official way to do it? Is there any kind of tutorial/sample?

Answered by DTS Engineer in 225814022

How extension is supposed to notify the user if transfer fails and is non-retryable? What's Apple's vision of this?

I can’t speak to Apple’s “vision” of anything, but the notification side of things is easy to take care of on modern systems via the UserNotifications framework, which can be used by both apps and extensions.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

What is the official flow for handling background transfer events in share extension?

This is not well documented, alas. Historically I’ve pointed folks at my post about this on the old DevForums, but I think it’s time to move that post over to the new. I’ve taking the old post, updated it a little, and reposted it here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you. I've read this post in the past and it was quite enlightening. But, still, it does not answer the main quiestion.

"The workaround is to put the code that handles request completion in both your app and your extension (possibly reusing the code via a framework)."
How extension is supposed to notify the user if transfer fails and is non-retryable? What's Apple's vision of this? How do they do it in their own apps?


Basically, I want to design the app the way it would not be rejected from App Store. 🙂 From what I see so far (Google Drive, for example), this moment is completely overlooked by Apple and they "let slide" various workarounds. Which are:
- Calling containing app via traversing responder chain
- Insta-killing extension with exit(0)
- Doing transfers in foreground

In case there's no official solution, I wonder what is the safest workaround.


Update: As you correctly mentioned in your article, there's no way to give up NSURLSession voluntarily and it leads to a plethora of problems:

- We can't resume tasks in application:handleEventsForBackgroundURLSession:completionHandler: because obtaining session would lead to app owning the it until all tasks complete, effectively blocking extension process from adding tasks to it (though, this can be worked around by re-creating all pending tasks in application-private NSURLSession and calling invalidateAndCancel)

- We can't peek into shared session to show progress of a lengthy transfer (to show it in-app or, say, in today extension) - for the same reason
- We can't access shared session at any time to cancel its tasks (when user signs out from the app, for example) - because it can still be owned by extension process

Accepted Answer

How extension is supposed to notify the user if transfer fails and is non-retryable? What's Apple's vision of this?

I can’t speak to Apple’s “vision” of anything, but the notification side of things is easy to take care of on modern systems via the UserNotifications framework, which can be used by both apps and extensions.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Wow, you're a lifesaver! This is really works well. Only sad thing, it's not available on pre-10.0 devices (extensions were added in iOS 8 and there are number of popular devices "stuck" on iOS 9.x), so in these cases, developers have to resort to some workarounds, like foreground transfers or IPC + Background Fetch, i guess.

So what’s the solution?

Share extension: proper way to handle background transfers
 
 
Q