UIDocumentInteractionController stopped working iOS 8
Asked Answered
A

3

5

I have a PDF file saved in the document directory. The path to the file is stored in a NSString property 'self.URL'. Here is my code to present the activity items:

-(void)presentDocumentInteractionController{
    self.docController = [UIDocumentInteractionController interactionControllerWithURL:self.URL];
    self.docController.delegate = self;
    [_docController setUTI:@"com.adobe.pdf"];
    [_docController presentOptionsMenuFromBarButtonItem:self.activityBarButton animated:YES];
}

Before iOS 8 this code worked fine. The user was presented with a list of items such as print, copy and email to choose from. After upgrading to iOS 8 /XCode 6, I'm getting this runtime error (it doesnt crash the app):

Unknown activity items supplied: (
    "<UITextViewPrintFormatter: 0x7f908ba53ca0>"
)

How can I solve this problem?

Alexanderalexandr answered 23/9, 2014 at 21:33 Comment(5)
Log self.URL. What is it?Beisel
it is: file:///Users/me/Library/Developer/CoreSimulator/Devices/272C49D3-7D19-4F03-A171‌​-78A7EAE1B02D/data/Containers/Data/Application/F70A1223-EDE0-472E-B94D-0B33AE5370‌​AE/Documents/filename.PDF The file exists in that address. The same URL property is used to load the PDF into a webview and it works there, but not for the document interaction controller.Alexanderalexandr
use presentOpenInMenuFromBarButtonItem instead presentOptionsMenuFromBarButtonItemPashto
@EugeneProkoshev didn't make a difference for me with the same problem as user1349768Petronella
how do you initiate your docController, is it in .h file? what properties do you use for that, maybe ARC is releasing everything when you leave the app to your pdf viewing app? I set it up in .h in interface UIDocumentInteractionController *docController; and @property (strong, nonatomic) then synthesize in .m file then use just docController no self., no _ works fineGillen
A
5

I have the same problem and have switched to using UIActivityViewController. However this makes the apps capable of opening the PDF no longer show up, so maybe that's not what you want.

Minimal Solution:

If you want to do minimal work, you don't even need to read your PDF into NSData, use a NSURL as activity item and iOS seems to know what to do:

- (void)share:(id)sender
{
    UIActivityViewController *activity =
        [[UIActivityViewController alloc] initWithActivityItems:@[self.URL]
                                          applicationActivities:nil];
    if ([activity respondsToSelector:@selector(popoverPresentationController)]) {
        activity.popoverPresentationController.barButtonItem = <# BAR BUTTON ITEM #>;
    }
    [self presentViewController:activity animated:YES completion:NULL];
}

Original Answer:

Make your view controller adhere to the UIActivityItemSource protocol, then you can do:

- (void)share:(id)sender
{
    self.pdfData = [NSData dataWithContentsOfURL:self.URL];
    UIActivityViewController *activity = [[UIActivityViewController alloc] initWithActivityItems:@[self] applicationActivities:nil];
    if ([activity respondsToSelector:@selector(popoverPresentationController)]) {
        activity.popoverPresentationController.barButtonItem = <# BAR BUTTON ITEM #>;
    }
    [self presentViewController:activity animated:YES completion:NULL];
}

Adhering to the protocol if you have a PDF file is relatively simple. You can of course optimize and return smaller NSData and even a preview image, but minimally do this:

- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
    return _pdfData;
}

- (id)activityViewController:(UIActivityViewController *)activityViewController
    itemForActivityType:(NSString *)activityType
{
    return _pdfData;
}

- (NSString *)activityViewController:(UIActivityViewController *)activityViewController
    subjectForActivityType:(NSString *)activityType
{
    return self.title;
}

- (NSString *)activityViewController:(UIActivityViewController *)activityViewController
    dataTypeIdentifierForActivityType:(NSString *)activityType
{
    return @"com.adobe.pdf";
}
Artiste answered 28/9, 2014 at 16:51 Comment(0)
W
0

This solved the problem for me:

ObjC:

dispatch_async(dispatch_get_main_queue(), ^() {
    [_docController presentOptionsMenuFromRect:button.bounds inView:button animated:YES];
});

Swift:

if let docController = UIDocumentInteractionController(URL: url) {
    dispatch_async(dispatch_get_main_queue()) {
         docController.presentPreviewAnimated(true)
    }
} else {
    // handle nil docController 
}

I don't use swift so this code might not work.

Windswept answered 24/10, 2014 at 9:49 Comment(4)
Please take a close look at meta.stackexchange.com/questions/104227/…. You seem to be answering the same thing to multiple questions which is not the appropriate thing to do.Bespoke
I'm unsure that your solution works as is for every question, so you need to make sure that your solution solves the issue of each question. If this is the case the correct thing to do is vote to close as duplicate.Bespoke
can you convert this to swift? ^() can't use in swiftYolanda
@Yolanda do you perhaps make use of presentOpenInMenuFromBarButtonItem ? i am not getting it to work correctlyCassatt
O
0

Use

- (BOOL)presentOpenInMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;

Instead of

- (BOOL)presentOptionsMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
Offenseless answered 1/11, 2014 at 7:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.