Question

How does one get a PDFView to display a PDF without having to resize the window or doing a scroll to force a redraw.

It's as if a setNeedsDisplay needs to be done, yet that has no effect.

I've the simplest app I can think of to display a PDF using a PDFView.

Basically create a new app in Xcode and change the code to be:

// AppDelegate.h
#import <Cocoa/Cocoa.h>
#import <Quartz/Quartz.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet PDFView *pdfView;
@end

and

// AppDelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize window = _window;
@synthesize pdfView = _pdfView;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSURL *pdfURL = [[NSBundle mainBundle] URLForResource:@"TestPage" withExtension:@"pdf"];
    PDFDocument *document = [[PDFDocument alloc] initWithURL: pdfURL];     
    self.pdfView.document = document;
}
@end

I've noticed the same behaviour in the Apple code example PDFKitLinker2 where one has to either scroll over the PDF or resize the window to get the PDF to display.

Granted I'm new to the world of Cocoa development but I've searched and found no really small examples that show how to display a PDF. What I've produced would seem to be correct yet I have doubts given that even PDFKitLinker2 doesn't seem to be correct.

I've created a Git repo of an Xcode project that demonstrates the issue for those that have time to help and/or comment.

git clone git@bitbucket.org:sotapme/pdfview_open.git

Using Xcode Version 4.3.3 (4E3002) - Latest Lion.

Thanks in advance for any help.


A Solution that works.


I found a solution whereby if I create a sub class of PDFView with an empty implementation and then add that as a custom view and wire it up my existing IBOutlet it works.

Makes no sense at all to me :(

//DPPDFView.h
#import <Quartz/Quartz.h>
@interface DPPDFView : PDFView
@end

and

//DPPDFView.m
#import "DPPDFView.h"
@implementation DPPDFView
@end

Apple's docs do say:

PDFView may be the only class you need to deal with for adding PDF functionality to your application. It lets you display PDF data and allows users to select content, navigate through a document, set zoom level, and copy textual content to the Pasteboard. PDFView also keeps track of page history.

You can subclass PDFView to create a custom PDF viewer.

I leave this question and self answer for those that may pass by with similar questions, hoping that it will be a dim beacon of light for them; Also hoping someone with more Cocoa wisdom will point out the error in my thinking.

Was it helpful?

Solution

I figured this is indeed caused by the PDFview needing a setNeedsDisplay after lazyloading has finished actually loading the PDF document.

A hack, but adding the below to your - (void)windowDidLoad method at least displays the document properly without needing a resize.

dispatch_async(dispatch_get_main_queue(), ^{
    [self.myPDFView setNeedsDisplay:YES];
});

OTHER TIPS

I found that setting the "Wants Core Animation" flag in the view results in some wonky behaviour. If you have that set, try adding:

[pdfView setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawOnSetNeedsDisplay];
[pdfView setNeedsDisplay: YES];

to your function that loads the PDFView.

It's an hypothesis, but it might be because when you self.pdfView.document = document; the PDFView out of the NIB hasn't been instantiated !

Obj-C doesn't shout at you when you pass messages to the nil object.

To test this hypothesis, you can NSLog() your pdfView to see if it is nil.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top