如何使用UIActivityViewController发送PDF文件

42

我正在尝试使用 UIActivityViewController 发送 PDF 文件。到目前为止,使用相当基本的方法一切都运行正常,但唯一的问题是当我选择通过邮件发送时,PDF 文件名为 Attachment-1 而不是我给文件的名称 Calculation.PDF

我不太在意标题的更改,但缺少 .pdf 扩展名似乎会在将文件发送给 Windows PC 的人时引起问题,因此我想解决这个问题。

我查看了以下链接: Control file name of UIImage send with UIActivityViewController

但是找不到一个等效的方法来:

[mailComposer addAttachmentData: UIImagePNGRepresentation(viewImage) mimeType:@"" fileName:@"myImage.png"];

那将能够与PDF文件一起使用。如果没有定制,这是否是无法修复的问题,还是有一个简单的解决方案?


你解决了这个问题吗?我也遇到了同样的问题。 - OWolf
这篇文章对我很有帮助:https://dev59.com/6XDYa4cB1Zd3GeqPBYzG#15826633,但缺点是你必须先保存文件。 - Michal Dobrodenka
8个回答

66

试试这个

NSData *pdfData = [NSData dataWithContentsOfFile:pdfFilePath];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[@"Test", pdfData] applicationActivities:nil];

[self presentViewController:activityViewController animated:YES completion:nil];

并且也

NSString *str = [[NSBundle mainBundle] pathForResource:@"AppDistributionGuide" ofType:@"pdf"];   
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[@"Test", [NSURL fileURLWithPath:str]] applicationActivities:nil]; 

7
@iTroyd23,我尝试按照您的建议操作,但无法设置附件的标题。所以,您能否描述一下如何设置附件的标题(例如,myPdf.pdf)? - Vatsal Shukla
只是想说我尝试了两种方法,对于一个XML文件,NSURL对我来说效果最好。 - lorenzo

19

Swift

let url = NSURL.fileURLWithPath(fileName)

let activityViewController = UIActivityViewController(activityItems: [url] , applicationActivities: nil)
        
presentViewController(activityViewController, animated: true, completion: nil)

14

Swift 4.0

这里附加了代码。我只是在呈现“activityViewController”之前添加了线程处理,因为此视图控制器在加载实际数据之前呈现。

let url = NSURLfileURL(withPath:fileName)

let activityViewController = UIActivityViewController(activityItems: [url] , applicationActivities: nil)

DispatchQueue.main.async {
            
    self.present(activityViewController, animated: true, completion: nil)
}

10

以上关于Swift的列表在Swift 3中已被弃用

let url = NSURL.fileURL(withPath: fileName)

let activityViewController = UIActivityViewController(activityItems: [url] , applicationActivities: nil)

present(activityViewController,
    animated: true,
    completion: nil)

4

用于 Objective-C 测试代码共享 PDF

- (void)downloadPDFfile:(NSString *)fileName withFileURL:(NSString *)shareURL {
    dispatch_async(dispatch_get_main_queue(), ^ {
        NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
        NSString *filePath = [documentDir stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@",[self generateName:fileName withFiletype:@"pdf"]]];
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:shareURL]];
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                                completionHandler:
                                      ^(NSData *data, NSURLResponse *response, NSError *error) {
                                          if (error) {
                                              NSLog(@"Download Error:%@",error.description);
                                          } else if (data && error == nil) {
                                              dispatch_async(dispatch_get_main_queue(), ^{
                                                  [data writeToFile:filePath atomically:YES];
                                                  [self shareFile:fileName withFilepath:filePath];
                                              });
                                          }
                                      }];

        [task resume];
    });
}

-(void)shareFile:(NSString*)withfileName withFilepath:(NSString*)filePath {
    NSMutableArray *items = [NSMutableArray array];

    if (filePath) {
        [items addObject:[NSURL fileURLWithPath:filePath]];
    }

    UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
    [activityViewController setValue:withfileName forKey:@"subject"];

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        activityViewController.modalPresentationStyle = UIModalPresentationPopover;
        UIPopoverPresentationController *popPC = activityViewController.popoverPresentationController;
        popPC.sourceView = self.view;
        CGRect sourceRext = CGRectZero;
        sourceRext.origin = CGPointMake(self.view.frame.size.width-30, 0);
        popPC.sourceRect = sourceRext;
        popPC.permittedArrowDirections = UIPopoverArrowDirectionDown;
    }

    [activityViewController setCompletionWithItemsHandler:
     ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {

     }];
    [self presentViewController:activityViewController animated:YES completion:nil];
}

-(NSString*)generateName:(NSString*)title withFiletype:(NSString*)type {
    NSString *subject = [title stringByReplacingOccurrencesOfString:@" " withString:@"_"];
    subject = [NSString stringWithFormat:@"%@.%@",subject,type];
    return subject;
}

下面是调用函数的方式

[self downloadPDFfile:@"yourFileName" withFileURL:shareURL];

2

针对Swift 3

您需要使用一个包含所需发送的PDF文件路径的URL数组。

let urlArray = [pdfPath1, pdfPath2]

然后创建一个UIActivityViewController:
let activityController = UIActivityViewController(activityItems: urlArray, applicationActivities: nil)

如果您正在使用UIBarButtonItem来执行该操作,您可以实现以下代码以防止在iPad上出现错误:

if let popover = activityController.popoverPresentationController {
   popover.barButtonItem = self.barButtonItem
}

最后,您需要展示activityController

self.present(activityController, animated: true, completion: nil)

0
Muruganandham K的回复简单而优雅。然而,在iOS 9中它不起作用。为了使其工作,如果您删除@[@"Test"并只传递pdfData,则会创建一个附件。
NSData *pdfData = [NSData dataWithContentsOfFile:pdfFilePath];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:pdfData applicationActivities:nil];

[self presentViewController:activityViewController animated:YES completion:nil];

-3

或许可以试试这个...

    #define IS_IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad

    // Validate PDF using NSData
    - (BOOL)isValidePDF:(NSData *)pdfData {
        BOOL isPDF = false;
        if (pdfData.length >= 1024 ) {

            int startMetaCount = 4, endMetaCount = 5;
            // check pdf data is the NSData with embedded %PDF & %%EOF
            NSData *startPDFData = [NSData dataWithBytes:"%PDF" length:startMetaCount];
            NSData *endPDFData = [NSData dataWithBytes:"%%EOF" length:endMetaCount];
            // startPDFData, endPDFData data are the NSData with embedded in pdfData
            NSRange startRange = [pdfData rangeOfData:startPDFData options:0 range:NSMakeRange(0, 1024)];
            NSRange endRange = [pdfData rangeOfData:endPDFData options:0 range:NSMakeRange(0, pdfData.length)];

            if (startRange.location != NSNotFound && startRange.length == startMetaCount && endRange.location != NSNotFound && endRange.length == endMetaCount ) {
                // This assumes the checkstartPDFData doesn't have a specific range in file pdf data
                isPDF = true;

            } else  {
                isPDF = false;
            }
        }
        return isPDF;
    }

    // Download PDF file in asynchronous way and validate pdf file formate.
    - (void)downloadPDFfile:(NSString *) fileName withFileURL:(NSString *) url {
        NSString *filePath = @"";
         dispatch_async(dispatch_get_main_queue(), ^ {
            NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
            filePath = [documentDir stringByAppendingPathComponent:[NSString stringWithFormat:@"/Attachments/%@",[self generateName:fileName withFiletype:@"pdf"]]];
            NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
            [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                if (error) {
                        NSLog(@"Download Error:%@",error.description);
                } else if (data && error == nil) {
                    bool checkPdfFormat = [self isValidePDF:data];
                    if (checkPdfFormat) {
                        //saving is done on main thread
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [data writeToFile:filePath atomically:YES];
                            NSURL *url = [NSURL fileURLWithPath:filePath];
                            [self triggerShare:fileName withFilepath:filePath];
                        });
                    }
                }
            }];
        });
    }

    // Trigger default share and print functionality using UIActivityViewController
    -(void) triggerShare:(NSString*)fileName withFilepath:(NSString*)filePath {
            * Set this available field on the activity controller */
            NSMutableArray *items = [NSMutableArray array];

            if (filePath) {
                [items addObject:[NSURL fileURLWithPath:filePath]];
            }

            UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
            [activityViewController setValue:fileName forKey:@"subject"]; // Set the mail subject.


            if (IS_IPAD) {
                activityViewController.modalPresentationStyle = UIModalPresentationPopover;
                UIPopoverPresentationController *popPC = activityViewController.popoverPresentationController;
                popPC.sourceView = self.view;
                CGRect sourceRext = CGRectZero;
                sourceRext.origin = CGPointMake(self.view.frame.size.width-30, 0 ); // I have share button in navigation bar. ;)
                popPC.sourceRect = sourceRext;
                popPC.permittedArrowDirections = UIPopoverArrowDirectionUp;
            }


            [activityViewController setCompletionWithItemsHandler:
             ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
             }];
            [self presentViewController:activityViewController animated:YES completion:nil];
    }

    -(NSString*) generateName:(NSString*)title withFiletype:(NSString*)type {

        NSString *subject = [title stringByReplacingOccurrencesOfString:@" " withString:@"_"];
        subject = [NSString stringWithFormat:@"%@.%@",subject,type];
        return subject;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接