7
votes

I have code to show a document as follows:

documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:self.thisUrl];

NSString *pathExtension = [self.thisUrl pathExtension];
if (pathExtension) {
    NSString *UTI = (__bridge NSString*)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)(pathExtension), NULL);
    if (UTI) {
        documentInteractionController.UTI = UTI;
    }
}
documentInteractionController.delegate = self;
[documentInteractionController presentOptionsMenuFromBarButtonItem:shareButton animated:YES];

When the options menu is displayed, it shows a list of apps that can open the document (e.g. Message), along with a list of actions below.

The options menu shows a list actions that is different from the menu shown in e.g., the Mail app.

The main difference is that the Mail app shows a "print" option, while my options menu does not. How do I get the options menu to show the print option?

The options menu shown in my app

The options menu shown in Mail

EDIT: I did a further test where I implemented the methods:

- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller canPerformAction:(SEL)action
{
  return YES;
}

- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller performAction:(SEL)action
{
  return YES; // or NO, doesn't matter
}

This had the effect of showing the "print", "copy" and "save to camera roll" actions in the popup view. Nothing happened when I tapped them, probably because I didn't properly implement -performAction. I also get a warning in the console log about using legacy methods.

This was a step backwards in some ways because I could no longer print some documents which were able to print correctly with the document interaction controller before I added those methods.

2
Have you tried implementing -documentInteractionController:canPerformAction: on your delegate and returning YES for print:? The method is deprecated because Apple wants people to use UIActivityViewController as of iOS 7, which you're not. Assuming Apple does, that might also explain the difference.Tommy
I don't want to use a deprecated method though, it will just result in getting rejected at some point in the future.1800 INFORMATION
I was originally using activity view controller, but it doesn't show the "open in" options that the document interaction controller has1800 INFORMATION
I'm not aware of Apple rejecting for use of a deprecated method but it does sound exactly like something they would do. But have you tried implementing that method merely as a diagnostic?Tommy
That's what deprecated generally means, after a while they will start rejecting apps1800 INFORMATION

2 Answers

2
votes

Apple encourage you to use UIActivityViewController. You can easily achieve this with that. However Print option is available only if your sharing content type supports printing. You can see a list of supported activities by data types here

- (IBAction)shareButton:(UIBarButtonItem *)sender
{
    NSString *textToShare = @"Text to share";
    NSURL *myWebContent = [NSURL URLWithString:@"http://yourpath.com/yourfile.pdf"]; // set your printable file here!

NSData *myData = [NSData dataWithContentsOfURL:myWebContent];


    NSArray *objectsToShare = @[textToShare, myData];

    UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:nil];

//Add exclusions here
    NSArray *excludeActivities = @[UIActivityTypeAirDrop,
                                   UIActivityTypeAssignToContact,
                                   UIActivityTypeSaveToCameraRoll,
                                   UIActivityTypeAddToReadingList,
                                   UIActivityTypePostToFlickr,
                                   UIActivityTypePostToVimeo];

    activityVC.excludedActivityTypes = excludeActivities;

    [self presentViewController:activityVC animated:YES completion:nil];
}
2
votes

I got this working using the QuickLook framework. I don't know why the "print" option sometimes doesn't appear for the document interaction controller, but then again, apparantly noone else does either.

The QuickLook framework supports previewing some document types but not all, so I left in my previous view controller and the document interaction controller for those unsupported types.

Below is a snippet of my working code.

@interface PreviewItemDataSource ()
@property (nonatomic, retain) NSURL* item;
@end

@implementation PreviewItemDataSource

@synthesize item=_item;

+(PreviewItemDataSource*)dataSourceWithItem:(NSURL*)item
{
    PreviewItemDataSource *source = [[PreviewItemDataSource alloc] init];
    source.item = item;
    return source;
}

-(NSInteger) numberOfPreviewItemsInPreviewController:(QLPreviewController*)controller {
    return 1;
}

- (id<QLPreviewItem>) previewController:(QLPreviewController*)controller previewItemAtIndex:(NSInteger)index {
    return self.item;
}

@end

@interface AppDelegate ()
@property (nonatomic, retain) PreviewItemDataSource *dataSource;
@end

...

-(void) openExternalFile:(NSString*) filePath withDelegate:(id<ChildBrowserDelegate>)delegate
{
    if ([filePath length] == 0)
        return;

    NSURL *item = [NSURL URLWithString:filePath];
    if (item && [QLPreviewController canPreviewItem:item]) {
        [self openQuickLookForItem:item];
    } else {
        // previous method unchanged
    }
}

- (void) openQuickLookForItem:(NSURL*)item {
    QLPreviewController *controller = [[QLPreviewController alloc] init];
    PreviewItemDataSource *dataSource = [PreviewItemDataSource dataSourceWithItem:item];
    controller.dataSource = dataSource;
    controller.modalPresentationStyle = UIModalPresentationFullScreen;
    [controller setCurrentPreviewItemIndex:0];

    [self.viewController presentViewController:controller animated:YES completion:nil];

    self.dataSource = dataSource;
}