前言
我们在开发iOS的项目中多多少少会遇到加载pdf的需求,前段时间项目中需要将网络的pdf显示出来,原本以为很简单的一个小需求,用WKWebView加载pdf的url即可,没想到却颇费了一番周折。先简单的介绍一下大概吧,这个pdf是一个电子处方,上面有一些医生开具的药品处方及基本信息,最大的不同点是医生的签名是一个电子签章(类似于公司办公用的印章),将pdf的url丢给WKWebView 后,发现了一个问题,就是在iOS12之后WKWebView可以将这个红色的电子签章显示出来,但是在iOS之前除了电子签章不能显示外其他信息均正常显示,网上说WKWebView在iOS12之后做了一些优化,但是不管这么说,我们的目的是要这个红色的电子签章在不同的系统都要显示出来,于是就有了这篇文章,希望能帮助以后有这类似需求的人能少走一些弯路。
iOS中PDF显示的几种方式
- WKWebView
- QLPreviewController
- UIDocumentInteractionController
- 第三方pdf.js
WKWebView
最先使用的是WKWebView来显示pdf,iOS12之后红色签章可以正常显示,为了处理iOS12以下的系统,网上说可是使用pdf.js来加载,这里对pdf.js的使用不做过多的介绍,网上的集成使用教程都写的比较详细了pdf.js使用,这里只说下我在使用的过程中遇到的一些问题。这个pdf是我们是存储在阿里云的服务器上,url中加了一个过期的验证,也就是说这个url过一段时间就会失效,在显示的时候需要重新获取这个url,第一个问题就是,直接使用url加载的话会报错,不能正常显示,原因未知,使用其他不带红色签章的pdf url可以正常显示。于是我将pdf下载到本地,用pdf.js去渲染的话,可以显示红色的签章,但是渲染的时间较长,大概平均4-5分钟(pdf不是很大,1M左右),于是我最终折腾了半天,放弃了使用pdf.js加载的方案。最终方案:对于iOS12之后的系统使用WKWebView加载,之前的系统使用QLPreviewController来显示。
if ([UIDevice currentDevice].systemVersion.floatValue >= 12.0) {
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"pdf的url"]];
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];
[self.webView loadRequest:request];
}
QLPreviewController
对于这QLPreviewController
之前也是没有接触过,它可以显示一些文档,图片,pdf,音乐文件等,可以说是功能非常的强大了,他的使用页比较简单,和UITableView类似。
首先导入#import
,创建一个 QLPreviewController
对象并实现QLPreviewControllerDataSource
方法。
self.previewVC = [[QLPreviewController alloc] init];
self.previewVC.dataSource = self;
#pragma mark - QLPreviewControllerDataSource
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller{
return 1;// 这里我只需要显示一个pdf,大家可根据具体的业务需要填写
}
- (id)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
return self.fileURL;// 这里的这个url是我将pdf下载到本地后的存储路径。
}
对于pdf显示我先是将pdf下载到本地,加载的本地路径(直接显示pdf的网络url不能正常显示)
- (void)downLoadPDF{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf",@"test"]];
if ([fileManager fileExistsAtPath:filePath]) {
[self.activityIndicatorView stopAnimating];
[self.activityIndicatorView removeFromSuperview];
[self addChildViewController:self.previewVC];
[self.view addSubview:self.previewVC.view];
self.previewVC.view.frame = self.view.bounds;
self.fileURL = [NSURL fileURLWithPath:filePath];
[self.previewVC reloadData];
}else{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURL *URL = [NSURL URLWithString:self.downloadURL];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
// 下载到本地的pdf存储路径
self.fileURL = [NSURL fileURLWithPath:filePath];
return self.fileURL;
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
// 这里加了个loading的状态,大家可根据需要添加
[self.activityIndicatorView stopAnimating];
[self.activityIndicatorView removeFromSuperview];
if (!error) {
// 下载成功将QLPreviewController 的view添加到当前视图,刷新数据
[self addChildViewController:self.previewVC];
[self.view addSubview:self.previewVC.view];
self.previewVC.view.frame = self.view.bounds;
// 这便可以正常显示红色的签章
[self.previewVC reloadData];
}
}];
[downloadTask resume];
}
}
UIDocumentInteractionController
对于UIDocumentInteractionController
的使用方法网上的介绍已经很详细了,这里只说明一点这个类也可以显示pdf文件,并且支持分享。有序丫的同学可以戳下面的链接
https://www.jianshu.com/p/4089c35e40b3
https://github.com/RuningFish/WTSummary
希望大家可以点点小星星,比心。