18

I am creating a PDFViewer application. I have set the autoScale Property of the PDFViewer to true, so that it the view expands to the width of the screen. Works fine with large PDF documents. But when the document is a single page document, the page automatically scrolls down to the end of the page, instead of starting with the beginning. I just cant understand the root cause of it. What am I missing here?

catlan
  • 25,100
  • 8
  • 67
  • 78
Adwait
  • 290
  • 2
  • 11

9 Answers9

9

This is what I did, it's a bit hacky

if let scrollView = pdfView.subviews.first as? UIScrollView {
    scrollView.contentOffset.y = 0.0
}
Aaron Halvorsen
  • 2,610
  • 1
  • 23
  • 31
  • In case you want to scroll to the view's top, which includes the page's shadow, this seems to be the way to go, as the other answers scroll to the top of the page, so that the top shadow isn't visible. – chkpnt Jan 12 '23 at 08:41
8

I think this is a bug in PDFView.

As workaround I suggest to manually scroll top the top:

self.pdfView.document = pdfDocument;

NSPoint pt = NSMakePoint(0.0, [self.pdfView.documentView bounds].size.height);
[self.pdfView.documentView scrollPoint:pt];

Bug Reporter

rdar://37942090: PDFview scrolls to bottom of the page in single page document.

catlan
  • 25,100
  • 8
  • 67
  • 78
  • I find the bug still exits, do you know how to implement it in iOS11? – newszer Feb 27 '18 at 08:06
  • PDFKit on iOS doesn't give access to the underlaying UIScrollView. But try this message: `- (void)goToRect:(PDFRect)rect onPage:(PDFPage *)page;` ... I assume CGRectMake(0,0,1,1) may work – catlan Feb 27 '18 at 15:44
  • No visible @interface for 'UIView' declares the selector 'scrollPoint:' – Suhas Arvind Patil Jun 28 '18 at 07:23
8

I propose this solution for scrolling to top of first page (it works on iOS 11.3):

if let document = pdfView.document,
   let firstPage = document.page(at: 0)
{
    let firstPageBounds = firstPage.bounds(for: pdfView.displayBox)
    pdfView.go(to: CGRect(x: 0, y: firstPageBounds.height, width: 1.0, height: 1.0), on: firstPage)
}
Petro Novosad
  • 119
  • 1
  • 3
  • This was close but didn't work quite right on rotated and/or cropped pages. I posted my modification below. – Oded Jul 18 '18 at 05:40
  • 1
    This doesn't seem to be working with `pdfView.autoScale = true`. The pdf always opens at the bottom of the second page – Sylvan D Ash Oct 24 '18 at 08:11
  • Yes, this solution works (`autoScale` doesn't matter) and it scrolls to the top of the page. But in case you want to scroll a little bit further as a user would be able to do (so that the page's top shadow is visible), @aaron-halvorsen's anwser seems to be the way to go. – chkpnt Jan 12 '23 at 08:36
6

Looks like the go command needs to be done on the next run through the run loop to work reliably:

DispatchQueue.main.async
{
    guard let firstPage = pdfView.document?.page(at: 0) else { return }
    pdfView.go(to: CGRect(x: 0, y: Int.max, width: 0, height: 0), on: firstPage)
}

Tested on iOS 12

Evan Olcott
  • 61
  • 1
  • 2
4

Expanding on Petro's answer, I had some issues with rotated pages and cropped pages, but this seems to work universally. I actually tested it on rotated pages, along with an annotation in the corner to verify that I was selecting the right corner:

     guard let firstPage = pdfView!.document?.page(at: 0) else {
        return;
     }
     let firstPageBounds = firstPage.bounds(for: pdfView!.displayBox)
     switch (firstPage.rotation % 360) {
     case 0:
        topLeftX = firstPageBounds.minX
        topLeftY = firstPageBounds.maxY
     case 90:
        topLeftX = firstPageBounds.minX
        topLeftY = firstPageBounds.minY
     case 180:
        topLeftX = firstPageBounds.maxX
        topLeftY = firstPageBounds.minY
     case 270:
        topLeftX = firstPageBounds.maxX
        topLeftY = firstPageBounds.maxY
     default:
        print ("Invalid rotation value, not divisible by 90")
     }

     pdfView!.go(to: CGRect(x: topLeftX, y: topLeftY, width: 1.0, height: 1.0), on: firstPage)
Oded
  • 954
  • 12
  • 16
4

I was loading the document in viewDidLoad, then I moved it to viewDidAppear, and it worked for me.

exmav10
  • 41
  • 3
  • Good one. `viewDidLoad` does not seem to be the right place for modifying screen content, because layouts have not been processed yet... No need to set any offsets or frames on PDFView, when you first set its document in `viewDidAppear` – Rainer Schwarz Jul 19 '19 at 13:45
  • Thank you! This was a very important piece of information. – ataravati Sep 06 '19 at 17:48
1

The rotation of the PDFPage matters! This is the Objective-C version of Oded:

- (void)scrollToTopOfPage:(PDFPage *)page {
    CGRect pageBounds = [page boundsForBox:self.displayBox];
    CGFloat topLeftX = 0;
    CGFloat topLeftY = 0;
    switch (page.rotation % 360) {
        case 0:
            topLeftX = CGRectGetMinX(pageBounds);
            topLeftY = CGRectGetMaxY(pageBounds);
            break;
        case 90:
            topLeftX = CGRectGetMinX(pageBounds);
            topLeftY = CGRectGetMinY(pageBounds);
            break;
        case 180:
            topLeftX = CGRectGetMaxX(pageBounds);
            topLeftY = CGRectGetMinY(pageBounds);
            break;
        case 270:
            topLeftX = CGRectGetMaxX(pageBounds);
            topLeftY = CGRectGetMaxY(pageBounds);
            break;
        default:
            break;
    }

    [self goToRect:CGRectMake(topLeftX, topLeftY, 1, 1) onPage:page];
}
David Moe
  • 11
  • 1
1
if let document = PDFDocument(url: viewModel.url) {
        pdfView.document = document
        
        // avoid iOS autoscale issue
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
            self?.pdfView.autoScales = true
        }
    }

I used the work around to define the autoScales property a bit after the loading of the document. The first page is nicely fit on top then.

Marian König
  • 704
  • 6
  • 11
0

For Objective-C use:

PDFPage *firstPage = [pdfView.document pageAtIndex:0];
CGRect firstPageBounds = [firstPage boundsForBox:pdfView.displayBox];
[pdfView goToRect:CGRectMake(0, firstPageBounds.size.height, 1, 1) onPage:firstPage];
Henrik Hansen
  • 111
  • 2
  • 9