This question is about printing ALL content (including off screen content) of WKWebView. Currently (still, as of iOS 10.2 or OSX 10.12) there is NO working solution
NOTE from OP: This solution has the same issue that has existed for quite some time. If one uses the unpublished method and ignores the errors thrown and sets margins, paper size, and the following flags on NSPrintInfo: orientation = NSPaperOrientationLandscape
and horizontalPagination = NSPrintingPaginationModeAutomatic
, the result is the same as it has been for quite some time and which is a print dialog displays and the print preview has ONLY 1 page and which is missing the content off to the right. WKWebView does not understand how to paginate content off to the right.
There may be a solution worth investigating by subclassing the WKWebView and overriding knowsPageRange:
and some of the other print related methods for a View. Also this might work in the vertical direction. I didn't try that as my use case is the need to correctly paginate in the horizontal direction with HTML content in TABLE columns columns too far right to fit on one page. The above mentioned settings DID used to work in the WebView class then subsequently broke in both WebView and WKWebView - End NOTE from OP
I've successfully used the SPI -[WKWebView _printOperationWithPrintInfo:] passing the usual [NSPrintInfo sharedPrintInfo]. Note that you CAN'T use -runOperation on the returned NSPrintOperation. You must use -runOperationModalForWindow:.... which is quite similar. The problem resides in the WebKit internals that expects a running runloop and a preview to be made internally to know the number of pages.
It definitely works with offscreen content, if what you mean by offscreen is "not fully displayed on screen". I still have a WKWebView displayed in a window, but it's very tiny and only displays a very short fraction of the entire webview content (21 A4 pages!). Hope this helps!
PS: Tested on 10.12, 10.14 and 10.15. Code is like this:
SEL printSelector = NSSelectorFromString(@"_printOperationWithPrintInfo:"); // This is SPI on WKWebView. Apparently existing since 10.11 ?
NSMutableDictionary *printInfoDict = [[[NSPrintInfo sharedPrintInfo] dictionary] mutableCopy];
printInfoDict[NSPrintJobDisposition] = NSPrintSaveJob; // means you want a PDF file, not printing to a real printer.
printInfoDict[NSPrintJobSavingURL] = [NSURL fileURLWithPath:[@"~/Desktop/wkwebview_print_test.pdf" stringByExpandingTildeInPath]]; // path of the generated pdf file
printInfoDict[NSPrintDetailedErrorReporting] = @YES; // not necessary
// customize the layout of the "printing"
NSPrintInfo *customPrintInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict];
[customPrintInfo setHorizontalPagination: NSPrintingPaginationModeAutomatic];
[customPrintInfo setVerticalPagination: NSPrintingPaginationModeAutomatic];
[customPrintInfo setVerticallyCentered:NO];
[customPrintInfo setHorizontallyCentered:NO];
customPrintInfo.leftMargin = 0;
customPrintInfo.rightMargin = 0;
customPrintInfo.topMargin = 5;
customPrintInfo.bottomMargin = 5;
NSPrintOperation *printOperation = (NSPrintOperation*) [_webView performSelector:printSelector withObject:customPrintInfo];
[printOperation setShowsPrintPanel:NO];
[printOperation setShowsProgressPanel:NO];
// BOOL printSuccess = [printOperation runOperation]; // THIS DOES NOT WORK WITH WKWEBVIEW! Use runOperationModalForWindow: instead (asynchronous)
[printOperation runOperationModalForWindow:self.window delegate:self didRunSelector:@selector(printOperationDidRun:success:contextInfo:) contextInfo:nil]; // THIS WILL WORK, but is async