i've been struggling with the exact same issue for the last 3 days, and was desperately looking across the web for a solution, which I didn't find.
But I finally got it running, so here is my solution for this:
Add the following user script to WKWebViewconfig.userContentController:
WKUserScript *printScript = [[WKUserScript alloc] initWithSource:@"window.print = function() {window.webkit.messageHandlers.print.postMessage('print')}"
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
[webViewConfig.userContentController addUserScript:printScript];
[webViewConfig.userContentController addScriptMessageHandler:self name:@"print"];
=> this is the same as in Capturing window.print() from a WKWebview, with one crucial difference: forMainFrameOnly is set to NO, because we want to inject this in our iframe, and not only in the top window
- Define a message handler in the view controller holding your WKWebview:
In the header:
@interface MyViewcontroller : UIViewController <UIGestureRecognizerDelegate, WKNavigationDelegate, WKScriptMessageHandler>
Implementation:
-(void) userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
Use the message handler to retrieve iframe's source (which is your pdf), and use-it as printing item for iOS's PrintController:
-(void) userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
if([message.name isEqualToString:@"print"])
{
[self.webView evaluateJavaScript:@"window.document.querySelector(\"iframe\").src" completionHandler:^(NSString *result, NSError *error)
{
UIPrintInteractionController *printController = UIPrintInteractionController.sharedPrintController;
printController.printingItem = [NSURL URLWithString:result];
UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error)
{
if(!completed)
{
if(error != nil) NSLog(@"Print failed: \nDomain: %@\nError code:%ld", error.domain, (long) error.code);
else NSLog(@"Print canceled");
}
NSLog(@"Print completed!\nSelected Printer ID: %@", printController.printInfo.printerID);
};
if(printController != nil)
[printController presentAnimated:YES completionHandler:completionHandler];
}];
}
else
NSLog(@"Unrecognized message received from web page"); }
NOTE: i use window.document.querySelector(\"iframe\")
because our iframe does not have an id, otherwise I would have used window.getComponentByID
. This important in case you have multiple iframes, which was not my case
I hope this can help you and others as well!