arcticmatt
arcticmatt

Reputation: 2004

Using UIActivityViewController to share spreadsheets, videos, etc

I'm having a problem when using the UIActivityViewController to share spreadsheets and videos (and probably other file types). The problem is that the right type identifiers are not found. For example, when I try to attach a spreadsheet, as seen in the code below:

    let testFilePath = NSBundle.mainBundle().pathForResource("test_spreadsheet", ofType: "xlsx")
    let testData = NSData(contentsOfFile: testFilePath)
    let list = [testData]
    let activityViewController = UIActivityViewController(activityItems: list, applicationActivities: nil)
    navigationController.presentViewController(activityViewController, animated: true, completion: nil)

I get the following log message:

2014-08-20 16:45:58.035 TestExtensionPoints[12608:194174] Discovered extensions: {(
    <NSExtension: 0x7fb7fca13680> {id = com.asperasoft.faspex-app.FaspexExtension}
)} for attributes: {
    NSExtensionActivationRule =     {
        extensionItems =         (
                        {
                attachments =                 (
                                        {
                        registeredTypeIdentifiers =                         (
                            "public.data"
                        );
                    }
                );
            }
        );
    };
    NSExtensionPointName =     (
        "com.apple.share-services",
        "com.apple.ui-services",
        "com.apple.services"
    );
}

Note that the registered type identifier is public.data, instead of public.spreadsheet.

This differs from when I try to attach, say, a pdf or a png file. If I just change the file to a pdf, as seen in the code below (only the first line changes):

let testFilePath = NSBundle.mainBundle().pathForResource("test_pdf", ofType: "pdf")

I get the following log message, which indeed DOES have the desired type identifier:

    2014-08-20 16:50:52.973 TestExtensionPoints[12652:196132] Discovered extensions: {(
    <NSExtension: 0x7ff2534285a0> {id = com.asperasoft.faspex-app.FaspexExtension}
)} for attributes: {
    NSExtensionActivationRule =     {
        extensionItems =         (
                        {
                attachments =                 (
                                        {
                        registeredTypeIdentifiers =                         (
                            "com.adobe.pdf"
                        );
                    }
                );
            }
        );
    };
    NSExtensionPointName =     (
        "com.apple.share-services",
        "com.apple.ui-services",
        "com.apple.services"
    );
}

Does anyone know why this is happening, and does anyone have a workaround? I know I can just write the files and attach URLs, but that's not really the purpose of this exercise.

Extra Background: I'm mainly asking this because I'm making a share extension, and am experimenting with how the data will be passed to me. I have already covered the case where it is passed as a URL and as a UIImage. These other cases would be fine, except for the fact that I am not getting the type identifiers I need.

Upvotes: 1

Views: 2096

Answers (2)

Glen Low
Glen Low

Reputation: 4497

The system probably sniffs for familiar types like PNG and PDF and not for esoteric types. Since PNG and PDF can be identified from the starting bytes, the activity system doesn't strictly need a UTI to identify them. However, the same may not be true of esoteric types like spreadsheets.

What you need is to implement UIActivityItemSource or subclass UIActivityItemProvider and provide these instances to the UIActivityViewController instead of naked NSData. This allows you to provide the UTI of the data explicitly to the UIActivityViewController.

For immediately available data, implement these UIActivityItemSource methods:

  • - activityViewControllerPlaceholderItem: to return the minimum data item that conforms to the type. You can probably pass an empty NSData here.

  • - activityViewController:itemForActivityType to return the actual data item.

  • - activityViewController:dataTypeIdentifierForActivityType: to return the UTI of the data item.

For data that can be lazily generated in another thread, implement these UIActivityItemProvider methods:

  • - item to return the actual data item. This will be called in a different thread, so your generation has to be thread safe.

  • - activityViewController:dataTypeIdentifierForActivityType: to return the UTI of the data item.

Now if the UTI is not a common UTI you'll also have to export them from your Info.plist.

Upvotes: 2

Gutblender
Gutblender

Reputation: 1350

Perhaps there's not a UTI for .xlsx files?

This question seemed to have a similar issue. The answer provided answers for .xlsx files, and more UTIs are listed here with instructions on implementation here.

Upvotes: 0

Related Questions