Sorry I misunderstood you earlier.
So, we need a workaround. We'll employ JavaScript injection using WKUserScript
to catch the window.print()
function call within the WKWebView
. This is possible due to the interoperability of Swift with JavaScript within WKWebView
.
Now, let's dissect the code:
- Creating the print script: We construct a
WKUserScript
object with a JavaScript code snippet that redefines the window.print()
function. In our version, it sends a message using the WebKit message handler, window.webkit.messageHandlers.printHandler.postMessage('print')
.
let printScript = WKUserScript(
source: "window.print = function(){window.webkit.messageHandlers.printHandler.postMessage('print')};",
injectionTime: .atDocumentEnd,
forMainFrameOnly: true
)
- Injecting the script: We need to inject this script into the
WKWebView
via its configuration, which contains a user content controller. We also add a message handler for 'printHandler', which is going to catch the message we've set up in our JavaScript.
let config = WKWebViewConfiguration()
config.userContentController.addUserScript(printScript)
config.userContentController.add(self, name: "printHandler")
Setting up WKWebView: Now, initialize the WKWebView
with the configuration. However, the earlier warning arises due to the WebView being assigned to a weak property, which leads to its immediate deallocation. Hence, we're going to leverage the already set WKWebView
from the storyboard, which is managed by ARC.
URL Loading: Here, we load the URL as usual.
Handling the script message: WKScriptMessageHandler
protocol implementation helps us handle the receipt of the print message. When we receive the "printHandler" message, we call a native function printPage()
.
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "printHandler" {
printPage()
}
}
- Print Functionality: We use the
UIPrintInteractionController
to present the system print dialog in the printPage()
function.
private func printPage() {
let printInfo = UIPrintInfo(dictionary: nil)
printInfo.jobName = webVw.url?.absoluteString ?? "Document"
printInfo.outputType = .general
let printController = UIPrintInteractionController.shared
printController.printInfo = printInfo
printController.printFormatter = webVw.viewPrintFormatter()
printController.present(animated: true, completionHandler: nil)
}
This solution is somewhat a bridge between the webpage's JavaScript environment and our native code.
Now, if window.print()
function isn't being called as expected, you should inspect the JavaScript code running on the webpage. It's possible that the window.print()
function is being defined after the page load, overriding your custom function. You can use polling to consistently check for the definition of window.print()
function, and replace it with your custom function if it's been overwritten.
Finally, this solution assumes that the webpage is executing the window.print()
function to initiate printing. If the page uses a different mechanism, this solution won't work, and we'd need to inspect the page's JavaScript further.