10

I am try to display a PDF in UIWebView via NSURL. It works fine.

But I do not know the height of pdf document. So sometimes it creates blank space or need to scroll. The PDF may also contain multiple pages.

I only want to show first page if it contain multi pages.

My code is as follow:

NSURL *url = [NSURL URLWithString:@"http://www.eecs.harvard.edu/econcs/pubs/online.pdf"];
 NSURLRequest * request = [NSURLRequest requestWithURL:url];
    [web_large loadRequest:request];
    [web_large setScalesPageToFit:YES];

Right now, the WebView has a fixed height

Whymarrh
  • 13,139
  • 14
  • 57
  • 108
user2526811
  • 1,233
  • 4
  • 20
  • 54
  • If all you need is the height of the document, then this question is a duplicate. If you need the amount of occupied space in a given page, you may want to reconsider your approach because a PDF is by nature a Portable Document Format, transcending platforms and browsers. If that white space was intended by the document's creator, which it likely is when PDF documents are created as pages, you may consider displaying it. – SwiftArchitect Aug 30 '15 at 22:05

6 Answers6

3

Pradumna Patil's answer is correct. I combined your code with his, and it worked fine. Just paste the following lines into your project and see for yourself:

UIWebView *web_large = [[UIWebView alloc]init];
[self.view addSubview:web_large];

NSURL *url = [NSURL URLWithString:@"https://www.truthinadvertising.org/wp-content/uploads/2014/09/App-Store-Review-Guidelines.pdf"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[web_large loadRequest:request];
[web_large setScalesPageToFit:YES];

CGPDFDocumentRef pdfDocumentRef = CGPDFDocumentCreateWithURL((CFURLRef)url);
CGPDFPageRef pdfPageRef = CGPDFDocumentGetPage(pdfDocumentRef, 1);

CGRect pdfPageRect = CGPDFPageGetBoxRect(pdfPageRef, kCGPDFMediaBox);

float width = pdfPageRect.size.width;
float height = pdfPageRect.size.height;

CGRect screenRect = [[UIScreen mainScreen]bounds];
web_large.frame = CGRectMake(0, 0, screenRect.size.width, height*screenRect.size.width/width);
turingtested
  • 6,356
  • 7
  • 32
  • 47
2

Try this

There is this method:

size_t CGPDFDocumentGetNumberOfPages(CGPDFDocumentRef document)

That gives you the number of pages.

For ex.

NSURL *pdfUrl = [NSURL fileURLWithPath:yourPath];    
CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl);

Below code gives height of single page in pdf file

  float width = CGPDFPageGetBoxRect(pdfPageRef, kCGPDFMediaBox).size.width;
    float height = CGPDFPageGetBoxRect(pdfPageRef, kCGPDFMediaBox).size.height;

Hope it helps.

Pradumna Patil
  • 2,180
  • 3
  • 17
  • 46
  • Thanks for your answer! but it gives wrong height! e.g. it gives height of 800 but if I set 800 px height for web view then it seems lots of blank space! – user2526811 Aug 21 '15 at 11:51
  • @user2526811 the dimensions from CGPDFPageGetBoxRect is the document's native dimensions, you need to set the height of the web view to "web_large.frame.size.width * (height / width)", so the height is a ratio of the document size – SomeGuy Aug 28 '15 at 06:20
2

in Swift you can do:

let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let writePath = documents?.appending("/myPdf.pdf")
let pdf: CGPDFDocument! = CGPDFDocument(URL.init(fileURLWithPath: writePath!) as CFURL)`enter code here`
let firstPage: CGPDFPage = pdf.page(at: 1)!
let heightFirstPage :CGRect =  firstPage.getBoxRect(.mediaBox) 
var heightPagePdf : CGFloat = heightFirstPage.height;

the variable 'pdf' also has a property 'numberOfPages', so you can know the entire height of pdf document (pdf.numberOfPages * heightPagePdf).

best regard

Alessio Campanelli
  • 970
  • 11
  • 19
1

This one is easy.

You have to access the scrollview of the webView not the webview itself:

CGFloat totalHeight = self.webView.scrollView.contentSize.height;
Jteve Sobs
  • 244
  • 1
  • 14
  • 2
    ^why isnt this accepted as the answer, this gives the desired height of the content of the pdf inside the webview quite correctly – Saheb Roy Aug 30 '15 at 17:35
  • The person specifically said "But __I do not know the height of pdf document__" and the title to the question is : "Get PDF document height in iOS WebView" i think my answer is pretty good for those circumstances @SwiftArchitect i think everyone else that answered it took it into a different direction – Jteve Sobs Aug 31 '15 at 00:49
  • Right. I could have sworn it did not start like that. Then is this not a duplicate of http://stackoverflow.com/questions/20755231/calculate-pdf-content-height-in-ios or http://stackoverflow.com/questions/3045587/how-to-get-actual-pdf-page-size-in-ipad? – SwiftArchitect Aug 31 '15 at 01:55
  • @SwiftArchitect I would agree it's a duplicate. But I'm just jumping on the bandwagon for a cheap shot at getting some rep ;) just being honest – Jteve Sobs Aug 31 '15 at 02:03
  • @SahebRoy It's not your job to evaluate that. However, you should upvote the answer if you find it useful. – turingtested Aug 31 '15 at 13:48
  • ^and what is my job exactly? – Saheb Roy Aug 31 '15 at 17:10
  • @SahebRoy i don't think he realizes someone commented after you/later deleted it, but none the wiser. brush it off – Jteve Sobs Aug 31 '15 at 19:08
0

Try this .. Its working fine

 NSURL* pdfFileUrl = targetURL;
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfFileUrl);

CGFloat pdfHeight = 0;
NSUInteger totalNum = CGPDFDocumentGetNumberOfPages(pdf);
 for(int i = 0; i < totalNum; i++ ) {
    CGPDFPageRef myPageRef=CGPDFDocumentGetPage(pdf, i+1);
    CGRect cropBox = CGPDFPageGetBoxRect(myPageRef, kCGPDFCropBox);
    pdfHeight+=cropBox.size.height;
    int pageRotation = CGPDFPageGetRotationAngle(myPageRef);
    CGSize pageVisibleSize = CGSizeMake(cropBox.size.width, cropBox.size.height);
    if ((pageRotation == 90) || (pageRotation == 270) ||(pageRotation == -90)) {
        pageVisibleSize = CGSizeMake(cropBox.size.height, cropBox.size.width);
    }
}
NSLog(@"%f",pdfHeight);
Jogendra.Com
  • 6,394
  • 2
  • 28
  • 35
0

Instead of loading pdf in webView I would like to suggest you to draw PDF in UIView, Like I have done in my own project and it's working perfect. Below is mine UIView subClass which draw pdf in UIView context.

PDFPage.h

#import <UIKit/UIKit.h>

@protocol PDFPageDelegate;



@interface PDFPage : UIView

@property    uint                   currentPage;
@property    unsigned long          totalPages;
@property    CGRect                 pageRect;
@property    NSString               *pdfPath;
@property    id<PDFPageDelegate>    delegate;


- (CGRect)setPdf:(NSString*)filePath;
- (void)swipeLeft;
- (void)swipeRight;
- (void)setPageNumber:(NSUInteger )targetPageNumber;

@end







@protocol PDFPageDelegate <NSObject>

- (void)pdfWillSwipeToLeft:(uint)upcommingPageNumber;
- (void)pdfWillSwipeToRight:(uint)upcommingPageNumber;
- (void)pdfTaped:(CGPoint)tapAt;
- (void)pdfDoubleTapped;

@end

PDFPage.m

#import "PDFPage.h"

@implementation PDFPage

@synthesize pageRect        = _pageRect;
@synthesize currentPage     = _currentPage;
@synthesize totalPages      = _totalPages;
@synthesize delegate        = _delegate;
@synthesize pdfPath         = _pdfPath;




- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {}

    _currentPage = 1;

    UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft)];
    swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    [self addGestureRecognizer:swipeLeft];


    UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight)];
    swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
    [self addGestureRecognizer:swipeRight];

    return self;
}



- (void)setPageNumber:(NSUInteger )targetPageNumber
{
    _currentPage = (uint)targetPageNumber;

    [self setNeedsDisplay];
    [UIView transitionWithView:self duration:0.5
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    [self.layer displayIfNeeded];
                } completion:nil];
}

- (void)swipeLeft
{
    if(_currentPage == _totalPages)
        return;

    _currentPage++;

    [_delegate pdfWillSwipeToLeft:_currentPage];

    [self setNeedsDisplay];
    [UIView transitionWithView:self duration:0.5
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    [self.layer displayIfNeeded];
                } completion:nil];
}

- (void)swipeRight
{
    if(_currentPage == 1)
        return;


    _currentPage--;


    [_delegate pdfWillSwipeToRight:_currentPage];


    [self setNeedsDisplay];
    [UIView transitionWithView:self duration:0.5
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    [self.layer displayIfNeeded];
                } completion:nil];

}



- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // PDF might be transparent, assume white paper
    [[UIColor whiteColor] set];
    CGContextFillRect(ctx, rect);

    // Flip coordinates
    CGContextGetCTM(ctx);
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -rect.size.height);

    // url is a file URL
    CFURLRef pdfURL = (__bridge CFURLRef)[NSURL fileURLWithPath:_pdfPath];
    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(pdfURL);
    CGPDFPageRef page1 = CGPDFDocumentGetPage(pdf, _currentPage);

    // get the rectangle of the cropped inside
    CGRect mediaRect = CGPDFPageGetBoxRect(page1, kCGPDFCropBox);

    CGContextScaleCTM(ctx, rect.size.width / mediaRect.size.width,
                  rect.size.height / mediaRect.size.height);
    CGContextTranslateCTM(ctx, -mediaRect.origin.x, -mediaRect.origin.y);

    // draw it
    CGContextDrawPDFPage(ctx, page1);
    CGPDFDocumentRelease(pdf);
}



- (CGRect)setPdf:(NSString*)filePath
{

    _pdfPath =filePath;
    _currentPage = 1;
    CFURLRef pdfURL = (__bridge CFURLRef)[NSURL fileURLWithPath:_pdfPath];

    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(pdfURL);
    CGPDFPageRef page = CGPDFDocumentGetPage(pdf,_currentPage);

    _pageRect = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
    _totalPages = (CGPDFDocumentGetNumberOfPages(pdf));
    [self setNeedsDisplay];
    [UIView transitionWithView:self duration:0.5
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    [self setNeedsDisplay];
                } completion:nil];

    CGRect finalRect = CGRectMake(0, 0, _pageRect.size.width, _pageRect.size.height);

    return finalRect;
}

How to use:-

    NSData *pdfData = [NSData dataWithContentsOfURL:[NSURL URLWithString:pdfPath]]; // here pdfPath is webURL

    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * savePDFAt = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    savePDFAt = [NSString stringWithFormat:@"%@/PDFs/",savePDFAt];
    [[NSFileManager defaultManager] createDirectoryAtPath:savePDFAt withIntermediateDirectories:NO attributes:nil error:nil];
    [savePDFAt stringByAppendingPathComponent:"test.pdf"];

    if([pdfData writeToFile:savePDFAt options:0 error:&error])
        NSLog(@"PDF download complete");

    PDFPage *pdfPage = [PDFPage new];
    pdfPage.alpha = 0.0f;
    pdfPage.delegate = self;
    pdfPage.frame = [pdfPage setPdf:pdfPath];

Then add this pdfPage to self's view or to scroller.

Anand Suthar
  • 3,678
  • 2
  • 30
  • 52