iOS开发PDF的显示与加载

作者: 蛮荒星域 | 来源:发表于2016-11-16 16:06 被阅读9785次

iOS开发PDF的显示与加载

前言

在实际的开发过程中,我们会遇到一些需要显示PDF的场景,比如一些表单,比如官方文件(为了保证原有的格式显示正常,通常会做成PDF来展示),这里我们来讨论一个展示PDF的方式。

PDF可能是网络加载的,也可能是本地的,我们现在来分别讨论。

网络加载

这种方式是提供了PDF的URL,iOS直接提供的根据URL来展示的方式目测有UIWebView和QLPreviewController
UIWebView

    NSURL *pdfURL = [NSURL fileURLWithPath:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:pdfURL];
    //设置缩放
    [self.webView setScalesPageToFit:YES];
    [self.webView loadRequest:request];```
    
但是要注意一点,UIWebView加载PDF文件的过程,在不同的iOS系统中有一些区别(诸如iOS8以及iOS9)。在加载HTML时,当方法`- (void)webViewDidFinishLoad:(UIWebView *)webView`执行时,大多数情况下,网页已经加载完成,可以做进一步的操作。但是在加载PDF时,在iOS8的系统中,仅仅只是加载了UIWebPDFView控件,而其中的UIPDFPageView还没有进行插入,我们不能做具体的操作,这个时候可以在viewDidLayoutSubviews中进行进一步操作。

**QLPreviewControlle**r的具体使用将在本地加载中详述,因为完全一样

### 本地加载
有很多都只是提供了URL的PDF链接,机智的boy会把保留在本地,避免重复下载,节省流量和时间。有的也是直接就放在本地的,变化的可能性很小。那么对于放在本地的应该如何处理呢?这里也有几种方式。

* UIWebView 这是一种通用的方式,对于本地的PDF展示也是如此,只要把上面的fileName换成本地的文件地址即可。但是这个方式有个很大的弊端,就是只有最基本的展示,不能放大缩小,也没有其他的相关交互,当然,混编除外,可是有必要这样做吗?对于已经处理好的PDF而且仅仅最基本展示,这种方式最方便。
* 利用CGContextDrawPDFPage,这种方式我并不熟悉,所以这里只是提一下,有兴趣的朋友可以自己找一下相关资料。
* QLPreviewController 这是系统提供的预览方式,其实展示起来效果也差不多,支持放大缩小的手势,还自带系统分享功能。  
* 使用强大的第三方[Reader(vfr)](https://github.com/vfr/Reader),这个很强大,功能很多,也提供了一些自定义的控制常量。诸如`READER_FLAT_UI`的。想要扩展的话,可以自己改写ReadViewController文件
 
 现在来具体讲述一下这几种方式的使用:
 
####  UIWebView
诸如加载网络PDF
```//self.fileName指向文件的全路径
    NSURL *pdfURL = [NSURL fileURLWithPath:fileName];
    NSURLRequest *request = [NSURLRequest requestWithURL:pdfURL];
    //设置缩放
    [self.webView setScalesPageToFit:YES];
    [self.webView loadRequest:request];```
    
####  QLPreviewController
* QLPreviewController需要用到QuickLook.framework,要在工程文件,Build Phases -> Link Binary With Libraries 中添加
* 在要使用的文件中导入QuickLook/QuickLook/h头文件,这是系统的,要用尖括号
* 加入代理QLPreViewControllerDelegate
* 在要使用的地方加入

QLPreviewController * qlPreview = [[QLPreviewController alloc]init];
qlPreview.dataSource = self; //需要打开的文件的信息要实现dataSource中的方法
qlPreview.delegate = self; //视图显示的控制
[self presentViewController:qlPreview animated:YES completion:^{
//需要用模态化的方式进行展示
}]; ```
这是模态化,也可以push,一样的。

  • 实现代理方法
-(NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller  
{  
    return _PDFArray.count; //需要显示的文件的个数  
}  
-(id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index  
{  
    //返回要打开文件的地址,包括网络或者本地的地址  
    NSURL * url = [NSURL fileURLWithPath:self.fileName];  
    return url;  
}  ```
还有其他的,这是DataSource,还有delegate中的相关方法,可以根据需要考虑是否实现。

#### Reader(vfr)
* 下载SDK,地址:https://github.com/vfr/Reader ,暂时不支持cocoapods,得手动导入
* 导入所需要的框架:
**MessageUI.framework** **ImageIO.framework** **QuartzCore.framework**
* 将Classes和Sources导入到项目中,建议还把Graphics也导入。
* 所需文件中导入**ReaderViewController.h**头文件,
以及添加代理**ReaderViewControllerDelegate**
* 使用:

NSString *path = [[NSBundle mainBundle] pathForResource:@"MobileHIG_iOS7_中文.pdf" ofType:nil];
ReaderDocument *doc = [[ReaderDocument alloc] initWithFilePath:path password:nil];
ReaderViewController *rvc = [[ReaderViewController alloc] initWithReaderDocument:doc];
rvc.delegate = self;
[self presentViewController:rvc animated:YES completion:nil];```

  • 实现代理方法
 - (void)dismissReaderViewController:(ReaderViewController *)viewController``` 
因为PDF阅读器可能是push出来的,也可能是present出来的,为了更好的效果,这个代理方法可以实现很好的退出

### 这里加个小tip(下载PDF到本地)
因为有时候使用诸如vrf之类的三方,并不支持URL的形式,需要加入到本地才可以,这个时候我们就需要将其下载到本地。我在这个提供几个方式供参考:

* 使用AFNetworking下载
* 使用NSData读取URL然后保存到本地文件的方式

详情参考Demo

> 
附github地址:
https://github.com/hllGitHub/PDFViewAndDownload
如果感兴趣或者觉得不错的话给个star,多谢了

相关文章

网友评论

  • __________mo:博主你好,最近做 PDF 遇到一个问题,不知怎么解决,我用 uiwebview 加载的,但是如果我直接用URL.init(fileURLWithPath: "/Users/user/Documents/SprayReceipts/SprayReceipts_IOS/TMSReceipts/TMSReceipts/test111.pdf")会报错,找不到文件,如果用URL.init(fileURLWithPath: Bundle.main.path(forResource: "test111", ofType: "pdf")!)就可以加载使用。是不是地址加载方式不对呢
    __________mo:@蛮荒星域 我准备换种方式去做了
    __________mo:@蛮荒星域 应该是沙盒路径改变了的原因吧
    蛮荒星域:@__________mo 首先,设置urlstring使用绝对路径或者相对路径都是可以的,正式使用要用相对路径,比如你的方式二,打包之后是找不到绝对路径了。另外一个问题,你的方式一使用是可以的,你可以检查一下你的路径是否错误了,你可以直接把文件拖到终端里面可以直接查看详细路径。
  • 92fb1c18dce6:难道楼主没有发现webView加载pdf特别慢么?
    蛮荒星域:@kinxcat webView加载是很慢啊,对于使用频率比较高的PDF建议保存到本地,或者首次通过webView预览,让用户选择将其保存到本地,下次直接本地打开会快很多。
  • 童话镇里蜿蜒的河:QLPreviewController 加载本地pdf 有些情况下,字母数字会不展示。怎么解决
  • coder_那一抹刚吹过的风:好萌的作者,忍不住给你评论了一下
  • 磐玉2:最近项目也要加入pdf浏览功能了。看了你的文章很有帮助。不过还有好多待解决,比如:目录解析,页码跳转定位,文本属性修改等功能。基本是冲着【微信读书】去的。。。
    把黑白变成彩色:我最近也是要做个pdf浏览,也是冲着微信读书的
  • 磐玉2:写得挺好的,加油!
  • CnnJmh:谢谢作者,期待可以编辑的出现。 最近可能要做pdf在线编辑,急需。
    CnnJmh:@LByy 这个我还真没做,当时是需求不明确,后来需求确定为保存而已。但是当时苹果手机也不支持这个预览,然后我就用的图片保存的。 我当时看了很多,有个大概的思路,但是不知道对不对,只能跟您说一下,你参考一下吧。 就是苹果没有自带的PDF编辑,只能以WebView展示,如果添加编辑功能的话,您只能往里面集成一系列的东西,可以参考一下别的PDF编辑软件,然后往这方面去深入学习一下。不好意思哦,没有帮到您。
    LByy:期待你的回复啊
    LByy:请问一下老铁,你的PDF编辑功能做好了嘛?选的什么方案啊,我最近也要做这个 想跟你聊一下这里面的功能,谢谢啊!!!
  • cf530b292c37:请教一下,怎么才能直接加载网络的url呢?我把网络url放到下面的代理方法里就直接崩了

    -(id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
    {
    //返回要打开文件的地址,包括网络或者本地的地址
    NSURL * url = [NSURL fileURLWithPath:self.fileName];
    return url;
    }
    蛮荒星域:这是预览。如果需要加载网络url,就得先下载到本地再使用这个方法打开
  • 微笑不是你:作者,这样签名。 签名看起来会很大。 能不能缩小的呢
    微笑不是你:@蛮荒星域 就是手写签名那里。看起来会比较大
    蛮荒星域:@微笑不是你 什么签名?
  • 蛮荒星域:为啥没有评论:sob:
    蛮荒星域:@嗜药 谢啦
    蛮荒星域:稍后还有一篇PDF可编辑的实现会分享给大家
    eb20824ed09c:写的不错,加油,特地登录给你评论

本文标题: iOS开发PDF的显示与加载

本文链接:https://www.haomeiwen.com/subject/kkizuttx.html