IOS development – PDF file loading and display (network, local)

Development environment: XCode7.3, Deployment Target:8.0

Saying that the company needs to display the project PDF file, and then searched the network, found the following methods:

1 the use of UIWebView loading, nothing to say, according to the file path, network or local can be, to create a NSURLRequest, and then loaded with webView on it, but only to display the file, it is low;

2 use UIDocumentInteractionController or QLPreviewController Preview – can still be very convenient to view PDF documents, but also some of the methods and features of the system, but this is not what I want.

3 the use of the third party – Reader (VFR), the function is very powerful, configurable high, far beyond the scope of my needs, can not be more perfect. However, in my happy going to add it to the project, only to find the goods -_-||| PDF resource could not be loaded on the network so I try to download the file to the local network, written into the sandbox cache directory, and then loaded or not…… Hard to look for a while, it seems to be written in the sandbox doc directory, and then download the file to the doc directory, and then can not load%> _<% good, had to do it yourself. Brothers and sisters have been successfully used, Wan Wang advice

4 to write their own, of course, this is also the article to write, features include: access to the network / local PDF files and display, you can achieve the effect of amplification or shrink display.

The following goods:

Project ideas (this is very important, only copy the code is able to achieve functional, but…… ):

The first step is to get PDF resources. Bundle resources will not say, if your PDF files are present in the Bundle, then the use of Reader (VFR) is the best, we only say network and local resources (well, very simple difference between local resources and cyber source lies in their different URL address so, we only said cyber source of local resources, corresponding to it, replace the URL address.)

The following method returns an CGPDFDocumentRef formatted data through a URL string, and you may see that this is not a OC method, yes, it is not.

< code>

< pre>

CGPDFDocumentRef test (NSString*urlString) {

NSURL*url = [NSURLURLWithString:urlString]; / / string into a NSURL address for incoming

CFURLRefrefURL = URL (__bridge_retainedCFURLRef); / / to NSURL into the CFURLRefrefURL reserve

CGPDFDocumentRefdocument =CGPDFDocumentCreateWithURL (refURL); / / get the file content by CFURLRefrefURL

CFRelease (refURL); / / CFURLRefrefURL release after burn the bridge after crossing it, this thing is not accepted, automatic memory management, so the manual release

If (document) {

Return document; / / return access to data


Return NULL; / / if no access to data, it returns NULL, of course, you can add the print log in here, convenient you find a problem



< /pre>

< /code>

The second step will be displayed, access to the data well, here is not a word to fix the details we need.

First of all, we get the PDF resources in all likelihood not only a page, but a lot of pages, so it is impossible to display in the same view. Then we need to obtain a separate page data to PDF data resources, don’t panic, system has a special function; then we also need to know about the PDF resources and how many pages, don’t panic, this system also has a special function, we will show them when.

Secondly, to get the data on a page, we have to show it to a view above, and finally a lot of view collection is all we need to show.

So, we need a custom view, then the incoming CGPDFDocumentRef data we have obtained by the above method and to display pages, let the view to display the corresponding page of the contents of the PDF file. Why do you need a view, because it will use Quartz2D graphics, the need to rewrite the view – (void) drawRect: (CGRect) rect method to achieve the PDF file content rendering)

Then the next step is to create a new view, inherited from UIView, where I named RiderPDFView, the following is the content of the.H file:


#import < UIKit/UIKit.h>

@interface RiderPDFView: UIView

/ / write a method, through Frame, have access to the CGPDFDocumentRef file and PDF file to display the page, to create a display of the contents of the PDF file view

– (instancetype) initWithFrame: (CGRect) frame documentRef: (CGPDFDocumentRef) docRef andPageNum: (int) page;



Then the contents of the.M file in the custom view


#import “RiderPDFView.h”

@interface (RiderPDFView) {

CGPDFDocumentRef documentRef; / / PDF resource data used to record the passed in

Int pageNum; / / record needs to display the page



@implementation RiderPDFView

/ / this method is not more to say……

– (instancetype) initWithFrame: (CGRect) frame documentRef: (CGPDFDocumentRef) docRef andPageNum: (int) page {

Self= [superinitWithFrame:frame];

DocumentRef= docRef;

PageNum= page;

Self.backgroundColor= [UIColorwhiteColor];



Re – (void) drawRect: / / (CGRect) rect method

– (void) drawRect: (CGRect) rect {

([selfdrawPDFIncontext:UIGraphicsGetCurrentContext)]; / / will transfer to the current context method, used for drawing


//- (void) drawRect: (CGRect) rect specific content

– (void) drawPDFIncontext: (CGContextRef) context {

CGContextTranslateCTM (context, 0, self.frame.size.height);

CGContextScaleCTM (context, 1, -1.0);

The above two is / / do a affine transformation on the environment, if not the implementation of the above two then draw out the PDF file will be an inverted effect, second sentences is the graphic display in the first sentence is upright, adjust the graphics position, if not implemented drawing will not in view of the visible range

CGPDFPageRef pageRef =CGPDFDocumentGetPage (documentRef, pageNum); / / get the need to draw the page data. The two parameter, the first number passed into the PDF resource data, the second is to pass through the need to display the page number

CGContextSaveGState (context); / / record the current rendering environment, prevent multiple painting

CGAffineTransform pdfTransForm =CGPDFPageGetDrawingTransform (pageRef, kCGPDFCropBox, self.bounds, 0, true); / / create a parameter affine transformation to a function. The first parameter is the corresponding page data; the second parameter is an enumeration value, I tried each one, seemingly no difference…… But the data are online to see with my current, so use it; the third parameter is the drawing area, I set the current view of the whole region, if necessary, nature can be amended; fourth is the rotation degree, there is no need to rotate, so as to set 0; fifth true, transfer, will keep the ratio of length to width

CGContextConcatCTM (context, pdfTransForm); / / create the parameters of affine transformation and context link

CGContextDrawPDFPage (context, pageRef); / / draw PDF data from the specified page to view

CGContextRestoreGState (context); / / restoringgraphis state



These are all the things you need to customize the view, where we have completed the rendering of the PDF file. The next step is how to get a better view.

Because the PDF file may be the font is very small, especially in the iPhone above, so you probably need to give him necessary to add a zoom function, or the direct use of webVie loading is not good, why do so many things.

When it comes to zoom in, I think the first time is to use UISCrollView to do, it can be more flexible than custom kneading gestures.

I first used the method of UISCrollView nested UISCrollView, nested in a UISCrollView three UISCrollView, the purpose is reached, but the amount of code and logic are too much, but in the moment of success, I think, there is a thing called UIColectionView…… So decisively qiantouming, use UICollectionView redo time, memory usage is reduced by 1/2. So here we use UICollectionView to complete the function. You basically did not use UICollectionView? Don’t panic, just die.

In order to achieve our zoom function, we need a custom UICollectionViewCell, then we create a new class, inherited from UICollectionViewCell, here I named CollectionViewCell, it is the contents of the.H file:


#import < UIKit/UIKit.h>

@class CollectionViewCell;

@protocol collectionCellDelegate


(void) collectioncellTaped: (CollectionViewCell*) cell;


The above is a / / agency agreement, a CollectionViewCell is clicked when the callback, you may need, may also not need

@interface CollectionViewCell: UICollectionViewCell

@property (nonatomic, strong) UIScrollView *contentScrollView; / / zoom function UISCrollView

@property (nonatomic, strong) UIView *showView; / / this is the reality of the contents of the PDF file view

@property (nonatomic, weak) ID < collectionCellDelegate> cellTapDelegate; / / agent



Then it’s the contents of the.M file


#import “CollectionViewCell.h”

#import “RiderPDFView.h”

@interface CollectionViewCell (&lt); UIScrollViewDelegate> / / UISCrollViewDelegate comply with the agreement, so as to achieve zoom


@implementation CollectionViewCell

/ / to override the init method.

– (instancetype) initWithFrame: (CGRect) frame {

If (self= [superinitWithFrame:frame]) {

_contentScrollView= [[UIScrollView alloc]initWithFrame:self.bounds]; / / initialize _contentScrollView

_contentScrollView.contentSize= frame.size; / / _contentScrollView content set size

_contentScrollView.minimumZoomScale=0.5; / / set the minimum zoom ratio

_contentScrollView.maximumZoomScale=2.5; / / set the maximum zoom ratio

_contentScrollView.delegate=self; / / set proxy

[self.contentView addSubview:_contentScrollView]; / / add _contentScrollView to CollectionViewCell

UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector (cellClicked)]; / / create gestures

[self addGestureRecognizer: tapGes]; / / add gestures to CollectionViewCell




This is the / / scrollView method, completed to realize through the scrollView zoom

– (UIView*) viewForZoomingInScrollView: (UIScrollView*) scrollView {

For (UIView*view in scrollView.subviews) {

If ([view isKindOfClass:[RiderPDFView class]]) {

Return view; / / return need zoom view





/ / to override the set method.

– (void) setShowView: (UIView*) showView {

For (UIView*tempView in _contentScrollView.subviews) {

[tempView removeFromSuperview]; / / remove all views in _contentScrollView


_showView= showView; assignment

[_contentScrollView addSubview:showView]; / / will need to add a view to display _contentScrollView


//tap event

– (void) cellClicked {

If ([self.cellTapDelegaterespondsToSelector:@selector (collectioncellTaped:)) {





All of the above preparations have been completed, followed by a full display of the PDF file in a view controller, the following is a ViewController.m content:


#import “ViewController.h”

#import “CollectionViewCell.h” / / import custom CollectionViewCell

#import “RiderPDFView.h” / / display the contents of the View file into PDF

@interface ViewController (&lt); UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate, collectionCellDelegate> / / abide by the agreement


UICollectionView *testCollectionView; / / show with CollectionView

CGPDFDocumentRef _docRef; access to the PDF resource file


@property (nonatomic, strong) NSMutableArray*dataArray; / / array data

@property (nonatomic, assign) int totalPage; / / the total number of pages



– (void) viewDidLoad {


_docRef=test (@; / / PDF file access resources through the test function, test function to achieve the above method for us, of course, the following was written again

[self getDataArrayValue]; / / get the need to show the data

UICollectionViewFlowLayout*layout = [[UICollectionViewFlowLayout alloc]init]; //UICollectionView need to pass a layout parameters when created, before the creation of it, first create a layout, use the system layout here.

Layout.itemSize=self.view.frame.size item CollectionView; / / set for each and every single element in the collection view of the size of each view we use a page to display, so that is currently the size of the view

[layout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; / / set the sliding direction for the horizontal direction, vertical direction can also be set to

Layout.minimumLineSpacing=0; / / set the item between the row

Layout.minimumInteritemSpacing=0; / / set the minimum distance of item

TestCollectionView= [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:layout]; / / create a set of views, set its size to the size of this view, we create the layout for the above layout

TestCollectionView.pagingEnabled=YES; / / set view a page turning

[testCollectionView registerClass:[CollectionViewCell class]forCellWithReuseIdentifier:@ “test”]; / / set view registered cell

TestCollectionView.delegate=self; / / set proxy

TestCollectionView.dataSource=self; / / set the data source

[self.view addSubview:testCollectionView]; / / will be added to the current view on the view


– (void) didReceiveMemoryWarning {



Get / / PDF resources by the address string

CGPDFDocumentReftest (NSString*fileName) {

NSURL*url = [NSURLURLWithString:fileName];

CFURLRefrefURL = (__bridge_retainedCFURLRef) url;

CGPDFDocumentRefdocument =CGPDFDocumentCreateWithURL (refURL);

CFRelease (refURL);

If (document) {






Get all / / PDF to display the page

– (void) getDataArrayValue {

Size_t totalPages =CGPDFDocumentGetNumberOfPages (_docRef); / / get the total number of pages

Self.totalPage= (int totalPages); / / to the global variable assignment

NSMutableArray*arr = [NSMutableArray new];

/ / create PDF to display the page through the cycle, and these pages are added to the array

For (inti =1; I < = totalPages; i++) {

RiderPDFView *view = [[RiderPDFView alloc]initWithFrame:CGRectMake (0,0, self.view.frame.size.width, self.view.frame.size.height) documentRef: _docRef andPageNum:i];

[arr addObject:view];


Self.dataArray= arr; / / to the data array assignment


There are several views / return collection partition

– (NSInteger) numberOfSectionsInCollectionView: (UICollectionView*) collectionView {



Returns a collection of view / / how many elements of nature is the total number of pages

– (NSInteger) collectionView: (UICollectionView*) collectionView numberOfItemsInSection: (NSInteger) section {

Return self.totalPage;


/ / reuse, return cell

– (UICollectionViewCell*) collectionView: (UICollectionView*) collectionView cellForItemAtIndexPath: (NSIndexPath*) indexPath {

CollectionViewCell*cell = [collectionViewdequeueReusableCellWithReuseIdentifier:@ “test” forIndexPath:indexPath];

Cell.cellTapDelegate=self; / / set the tap event agency

Cell.showView=self.dataArray[indexPath.row]; / / assignment, set the display in each item content



When the trigger / set view item is clicked after the event, according to the individual needs of writing

– (void) collectioncellTaped: (CollectionViewCell*) cell {

NSLog (@ “how did I order it? “);


/ / set view inherited from scrollView, so you can use a proxy scrollView event, here is the function when a item was not displayed in the current view, it will zoom ratio reduction

– (void) scrollViewDidEndDecelerating: (UIScrollView*) scrollView {

For (UIView *view in testCollectionView.subviews) {

If ([view isKindOfClass:[CollectionViewCell class]]) {

CollectionViewCell*cell = (CollectionViewCell*) view;







Then…… And then there is no function to achieve, if you need other features, you can add on this basis, anyway, I do not need any more, and more.

If there is a mistake, please correct me, refused to tear force, 3q.

Development environment: XCode7.3, Deployment Target:8.0 said, the company needs to display the project PDF file, then searched the network, found the following methods: