owenfi owenfi - 2 months ago 20
Objective-C Question

How to get an NSDocument subclass to print custom views

What needs to be hooked up for an NSDocument subclass to call its print methods when File->Print... is chosen?

How does the File->Print menu get hooked up? (Right now the selector/action is hooked up to first responder's print method. That's in a storyboard, while my NSDocument subclass has its own xib.)

I've tried implementing all of:

-(void)print:(id)sender;
-(void)printDocument:(id)sender;
-(void)printDocumentWithSettings:(NSDictionary *)printSettings showPrintPanel:(BOOL)showPrintPanel delegate:(id)delegate didPrintSelector:(SEL)didPrintSelector contextInfo:(void *)contextInfo;
-(NSPrintOperation*)printOperationWithSettings:(NSDictionary *)printSettings error:(NSError *__autoreleasing *)outError;


But none of them are ever called when I choose Print. Where are these methods supposed to go/who calls them? (I also tried a basic app with a custom view and didn't have luck there either.)

Answer

Okay. Looks like the problem is due to a bug in Xcode: When creating a Document based app using storyboards the file menu is by default hooked to print: and printDocument: is not available.

The strange part is that my print: call is getting hijacked somewhere along the line but I can't figure out where (at the application level, not the document, because the print dialog is a window not a sheet). printDocument: works as expected, but must be defined manually in order to hook it up.

This is for a document-based app, targeting 10.10, and using storyboards.

In the storyboard with Main Menu, add a User Defined Action for printDocument: (This is where storyboard based differs, and I feel is a bug. Xib based do not require this User Defined Action.)

Attributes Inspector for First Responder

Hook up the selector for File -> Print to First Responder and choose printDocument: instead of print:

Don't define printDocument: in your NSDocument subclass. If you want to, then be sure to call super or perhaps one of the methods below.

From NSDocument.h

/* The action of the File menu's Print... item in a document-based application.
The default implementation of this method merely invokes
[self printDocumentWithSettings:[NSDictionary dictionary]
  showPrintPanel:YES 
        delegate:nil
didPrintSelector:NULL
     contextInfo:NULL].
*/
- (IBAction)printDocument:(id)sender;

The default implementation of printDocumentWithSettings in turn calls printOperationWithSettings, so you can use either of those methods to draw custom information prior to the print sheet appearing.