TumblrArchive / ios-extension-issues

A collection of issues with iOS 8 share extensions, along with radar links, sample projects, and workarounds

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Background NSURLSessionUploadTask (share extension) cannot read file in app group shared container

irace opened this issue · comments

Apple’s App Extension Programming Guide contains a section on performing uploads and downloads, complete with sample code indicating how background sessions are to be used to perform uploads that may last longer than your extension process is alive for. Normally, an NSURLSessionUploadTask can be created from a stream, raw data, or a file URL, but only the latter is intended to be used in an extension. This makes sense: communication between extensions and container applications in the same “app group” occurs through a shared container, a special, secure location on disk that both extension and app are able to read and write from. The extension writes a file to the shared container and initiates a task to upload that file. The upload ostensibly occurs in a third process, allowing it to continue even once the extension has been terminated. The container application will then later be woken up and notified as to its success or failure.

We have not been able to get this to actually work.

In our experience, while our extension and container application can both access the shared container without issue, the NSURLSessionTask is seemingly unable to. Instead, it spits out errors that you can find in the radar.

Workaround

As soon as a user taps the “Post” button, we’d ideally like to dismiss the extension and let them get on with their day, while continuing to upload in the background. Given that we haven’t been able to get this to work, we’ve given our extension a progress bar and are keeping it on screen until the request completes. It’s possible that the user could background the host application, and iOS could kill it in order to reclaim the memory, but this seems like our best option given these limitations. We’ll happily go back to using background sessions if the issue we’re seeing ends up getting fixed.

An idea for an alternative and less intrusive workaround:

  • Create a directory on the shared container where the extension can leave bodies (E.G.: ./requests/)
  • The extension creates 2 files per wanted task: {Some-UUID}.request and {Some-UUID}.body, one containing NSURLRequest encoded with NSCoding (or whatever format you can latter translate to a NSURLRequest) and the body to send respectively.
  • Using background fetch or another method to get the app active, the host app is later woken up
    • Move the bodies to a directory within the app (to let the session access them).
    • Decode the requests and create tasks.
    • Delete the "{Some-UUID}.request" files so the task isn't created on a subsequent run.

The downside od this approach is it adds a delay since the tasks are not created immediately,

@dtorres This would work fine, but for Tumblr at least, it's crucial that we at least attempt to deliver a user's post as soon as they create it.

Background fetch might not occur for quite some time, so for us, this would be a non-starter.

We had the exact same issue but it was resolved in the GM.

@tijoinc Thanks for letting me know. I did test my sample project on the GM and saw the same errors, but will give it another shot.

@irace yeah, there's lots and lots of tiny configuration gotchas that I encountered along the way. Something might be off there too. If you have any more details I'll try'n help :)

@tijoinc Can you kindly provide a sample project that solves this issue if possible?

This appears to have been fixed, potentially as early as the iOS 8 GM (as reported by @tijoinc). I was able to create a sample project that successfully uploads using NSURLSession but have not had the time to attempt to update the Tumblr extension yet.