I have a document-based macOS app written in Objective-C, and each document window contains a scrollable NSTextView
. I know that printing can get complicated if you want to do nice pagination, but is there a quick and dirty way to get basic printing working? As it is, the print panel shows up, but its preview area is totally blank. Here's the current printing part of my NSDocument
subclass.
- (NSPrintInfo *)printInfo
{
NSPrintInfo *printInfo = [super printInfo];
[printInfo setHorizontalPagination: NSPrintingPaginationModeFit];
[printInfo setHorizontallyCentered: NO];
[printInfo setVerticallyCentered: NO];
[printInfo setLeftMargin: 72.0];
[printInfo setRightMargin: 72.0];
[printInfo setTopMargin: 72.0];
[printInfo setBottomMargin: 72.0];
return printInfo;
}
- (void)printDocumentWithSettings:(NSDictionary<NSPrintInfoAttributeKey, id> *)printSettings
showPrintPanel:(BOOL)showPrintPanel
delegate:(id)delegate
didPrintSelector:(SEL)didPrintSelector
contextInfo:(void *)contextInfo
{
NSPrintInfo* thePrintInfo = [self printInfo];
[thePrintInfo setVerticallyCentered: NO ];
NSPrintOperation *op = [NSPrintOperation
printOperationWithView: _textView
printInfo: thePrintInfo ];
[op runOperationModalForWindow: _docWindow
delegate: delegate
didRunSelector: didPrintSelector
contextInfo: contextInfo];
}
The trick here is to make an off-screen copy of your NSTextView and copy your contents into it. Here's an example of how to do that:
@IBAction func megaPrint(_ sender:Any?) {
let printView = megaTextView! // NSTextView from your on-screen view hierarchy
// make a new NSTextView copying the contents from your on-screen view
// make sure to set the frame
let printedView = NSTextView(frame: NSRect(origin:NSPoint(x:0, y:0), size:NSSize(width:480, height:200)))
printedView.isVerticallyResizable = true
printedView.isHorizontallyResizable = false
printedView.textStorage!.append(printView.textStorage!.copy() as! NSAttributedString)
// Create a new print operation and tell it to show the print and progress panels
// and set some options for positioning the text in pages
let printOperation = NSPrintOperation.init(view: printedView)
printOperation.showsPrintPanel = true;
printOperation.showsProgressPanel = true;
printOperation.printInfo.isVerticallyCentered = false
printOperation.printInfo.isHorizontallyCentered = false
// These days, users generally expect to be able to perform page setup style changes in the print panel, aliveating the need to open the Page Setup panel seperately. Expliclty opt into that here. Note: CharacterSheet.xib will use auto layout to automatically adjust to paper changes.
let printPanel = printOperation.printPanel
printPanel.options = printPanel.options.union([.showsCopies, .showsPageRange, .showsPaperSize, .showsOrientation])
// For fun, lets print our header and footer (note, the header is a blank string)
let printInfo = printOperation.printInfo
printInfo.dictionary()[NSPrintInfo.AttributeKey.headerAndFooter] = true
// Run the print operation. This will show the print sheet and peform preview and printing
// Note: As with normal sheets, code execution will not block on this line
printOperation.runModal(for: self.view.window!, delegate: nil, didRun:nil, contextInfo: nil)
}