iOS webview打印功能的实现(包含系统原生分享交互视图)

项目需求APP连接打印机,打印出APP里加载的PDF文件或H5网页。以下mark打印功能的开发。

//点击打印
-(void)printAction:(UIBarButtonItem *)sender
{
    if ([_url containsString:@".aspx"] || [_url containsString:@".html"]) { //打印H5网页
        /** Safari自带共享按钮,包含打印功能,可跳出APP打印
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"打印网页需前往Safari浏览器,并点击顶部共享按钮,即可选择“打印”" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
        UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"立即前往" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:_url]]) {
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:_url]];
            }
        }];
        [alertController addAction:action1];
        [alertController addAction:action2];
        [self presentViewController:alertController animated:YES completion:nil];
         */
        //直接弹出打印控制器打印网页
        UIPrintInteractionController *printController = [UIPrintInteractionController sharedPrintController];
        //打印完成回调
        void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
        ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
            if(!completed && error){
                NSLog(@"FAILED! due to error in domain %@ with error code %ld",
                      error.domain, (long)error.code);
            }
        };
        //配置打印信息
        UIPrintInfo *printInfo = [UIPrintInfo printInfo];
        printInfo.outputType = UIPrintInfoOutputGeneral; //输出类型,可打印文本、图形、图像
        printInfo.jobName = @"就医解读报告"; //打印工作标识
        printInfo.duplex = UIPrintInfoDuplexLongEdge; //双面打印绕长边翻页,NONE为禁止双面
        
        printController.printInfo = printInfo;
        printController.showsPageRange = YES;
        //格式化打印UIWebView上显示的内容
        UIViewPrintFormatter *viewFormatter = [self.webView viewPrintFormatter];
        viewFormatter.startPage = 0;
        printController.printFormatter = viewFormatter;
        /** 格式化打印HTML文档
         UIMarkupTextPrintFormatter *htmlFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:self.htmlString];
         htmlFormatter.startPage = 0;
         htmlFormatter.contentInsets = UIEdgeInsetsMake(72.0, 72.0, 72.0, 72.0);
         */
        /** 格式化打印简单文字
         UISimpleTextPrintFormatter *textFormatter = [[UISimpleTextPrintFormatter alloc] initWithText:@"嘛哩嘛哩哄发哈砂砾石"];
         textFormatter.startPage = 0;//指定从哪一张开始打印0代表第一张
         textFormatter.contentInsets = UIEdgeInsetsMake(36, 36, 36, 36);//72相当于1英寸,这样设置上下左右的边距都为0.5英寸
         textFormatter.maximumContentWidth = 504;//(72x7.5)相当于打印宽度为7英寸
         */
        
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            [printController presentFromBarButtonItem:sender animated:YES completionHandler:completionHandler];
            //或者 presentFromRect:inView:animated:completionHandler:
        }else{
            [printController presentAnimated:YES completionHandler:completionHandler];
        }
    
    }else{ //打印网络加载的PDF文件
        [MBProgressHUD showHUDAddedTo:self.view animated:YES];
        //首先需要下载下来
        [[HDNetworking sharedHDNetworking] downLoadWithURL:_url progress:nil destination:^NSURL * _Nullable(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
            //返回目的地路径
            NSString *cashPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
            return [NSURL fileURLWithPath:[cashPath stringByAppendingPathComponent:response.suggestedFilename]];
            
        } downLoadSuccess:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath) {
            [MBProgressHUD hideHUDForView:self.view animated:YES];
            DLog(@"response = %@, filePath = %@", response, filePath);
            _tempPath = filePath.path; //获取到本地文件路径
            
            //方法一:文件预览控制器打印,其不仅有打印功能,而且有保存、转发等功能
            
            self.previewController = [[QLPreviewController alloc] init];
            self.previewController.dataSource = self;
            self.previewController.delegate = self;
            [self presentViewController:self.previewController animated:YES completion:nil];
            
            //方法二:单纯用打印控制器打印PDF
            /*
             AirPrint可以直接打印一些内容。 这些内容是 NSData, NSURL, UIImage, and ALAsset 类的实例, 但是这些实例的内容, 或者引用的类型(NSURL)必须是 image 或者pdf.
             对于 image来说, NSData, NSURL, UIImage, and ALAsset 类型都可以的。 对于PDF, 只能使用 NSData, NSURL。 然后需要将这些数据实例直接赋值 给 UIPrintInteractionController实例的 printingItem 或者 printingItems 属性。
             */
            /*
            UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
            NSData *pdfData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:_tempPath]];
            if (pic && [UIPrintInteractionController canPrintData:pdfData]) {
                pic.delegate = self;
                
                UIPrintInfo *printInfo = [UIPrintInfo printInfo];
                printInfo.outputType = UIPrintInfoOutputGeneral;
                printInfo.jobName = @"就医解读报告";
                printInfo.duplex = UIPrintInfoDuplexLongEdge;
                pic.printInfo = printInfo;
                pic.showsPageRange = YES;
                pic.printingItem = pdfData;
                
                void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
                ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) {
                    if (!completed && error)
                        NSLog(@"FAILED! due to error in domain %@ with error code %ld",
                              error.domain, error.code);
                };
                if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
                    [pic presentFromBarButtonItem:sender animated:YES
                                completionHandler:completionHandler];
                } else {
                    [pic presentAnimated:YES completionHandler:completionHandler];
                }
            }
            */
        } failure:^(NSError * _Nonnull error) {
            [MBProgressHUD hideHUDForView:self.view animated:YES];
        }];
    }
    
    //内置Safari,功能较少
//    SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:_url]];
//    [self presentViewController:safariVC animated:YES completion:nil];
}

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

- (id <QLPreviewItem>)previewController: (QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
    return [NSURL fileURLWithPath:_tempPath];
}

- (void)previewControllerDidDismiss:(QLPreviewController *)controller
{
    if(![_tempPath isEqual:@""]){ //文件预览器dismiss,将下载到本地的文件移除
        NSFileManager * fileManager = [NSFileManager defaultManager];
        [fileManager removeItemAtPath:_tempPath error:nil];
    }
}

注意,使用文件预览器需要导入框架<QuickLook/QuickLook.h>和代理QLPreviewControllerDelegate,QLPreviewControllerDataSource 

根据项目需要,选择使用打印控制器还是文件预览器O(∩_∩)O~


//另附:UIActivityViewController、UIDocumentInteractionController的使用方法

//一、系统原生分享交互视图

//一、系统原生分享交互视图
    /*! 1. 创建要分享的数据内容,加在一个数组 ActivityItems里。 */
    NSString *textToShare = @"我是且行且珍惜_iOS,欢迎关注我!";
    UIImage *imageToShare = [UIImage imageNamed:@"wang.png"];
    NSURL *urlToShare = [NSURL URLWithString:@"https://github.com/wslcmk"];
    NSArray *activityItems = @[urlToShare,textToShare,imageToShare];
    //自定义 customActivity继承于UIActivity,创建自定义的Activity加在数组Activities中。
//    customActivity * custom = [[customActivity alloc] initWithTitie:@"且行且珍惜_iOS" withActivityImage:[UIImage imageNamed:@"wang"] withUrl:urlToShare withType:@"customActivity" withShareContext:activityItems];
//    NSArray *activities = @[custom];
    
    /*!
     * 2.创建分享视图控制器,初始化UIActivityViewController
     * ActivityItems  在执行activity中用到的数据对象数组。数组中的对象类型是可变的,并依赖于应用程序管理的数据。例如,数据可能是由一个或者多个字符串/图像对象,代表了当前选中的内容。
     * Activities  是一个UIActivity对象的数组,代表了应用程序支持的自定义服务。这个参数可以是nil。
     */
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@healthCare20160822163627HY2016.pdf",PER_REPORT_PATH]];
    UIActivityViewController *activity = [[UIActivityViewController alloc] initWithActivityItems:@[@"分享PDF", url] applicationActivities:nil];
    
    /*! 3、关闭系统的一些Activity类型,不需要的功能关掉。 */
    //Activity 类型又分为“操作”和“分享”两大类
    /*
     UIKIT_EXTERN NSString *const UIActivityTypePostToFacebook     NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypePostToTwitter      NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypePostToWeibo        NS_AVAILABLE_IOS(6_0);    //SinaWeibo
     UIKIT_EXTERN NSString *const UIActivityTypeMessage            NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypeMail               NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypePrint              NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypeCopyToPasteboard   NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypeAssignToContact    NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypeSaveToCameraRoll   NS_AVAILABLE_IOS(6_0);
     UIKIT_EXTERN NSString *const UIActivityTypeAddToReadingList   NS_AVAILABLE_IOS(7_0);
     UIKIT_EXTERN NSString *const UIActivityTypePostToFlickr       NS_AVAILABLE_IOS(7_0);
     UIKIT_EXTERN NSString *const UIActivityTypePostToVimeo        NS_AVAILABLE_IOS(7_0);
     UIKIT_EXTERN NSString *const UIActivityTypePostToTencentWeibo NS_AVAILABLE_IOS(7_0);
     UIKIT_EXTERN NSString *const UIActivityTypeAirDrop            NS_AVAILABLE_IOS(7_0);
     */
    activity.excludedActivityTypes = @[UIActivityTypePostToVimeo];
    
    [self presentViewController:activity animated:YES completion:nil];

二、文件交互控制器

@property(nonatomic,strong)UIDocumentInteractionController *docController;

    //二、文件交互控制器
    _docController = [UIDocumentInteractionController interactionControllerWithURL:[[NSBundle mainBundle] URLForResource:@"meinv" withExtension:@"gif"]];
    //功能一:分享文件
//    [_docController presentOpenInMenuFromRect:self.view.bounds inView:self.view animated:YES];
    //展示更多可选项
//    [_docController presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];

    //功能二:预览文件
    //预览文件需遵循代理UIDocumentInteractionControllerDelegate
//    _docController.delegate = self;
//    [_docController presentPreviewAnimated:YES];

#pragma mark - UIDocumentInteractionControllerDelegate
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
    return self;
}

- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
    return self.view;
}

- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller
{
    return self.view.frame;
}
注意:UIDocumentInterRactionController定义的时候一定要是设置一个strong类型的属性,因为必须要对该对象进行持有;
当上述方法确实无法满足你的要求的时候就可以考虑一下用Quick Look了。

猜你喜欢

转载自blog.csdn.net/txz_gray/article/details/78780098