UIPrintInteractionController 始终显示当前 WKWebView 而不是 iFrame 内容
UIPrintInteractionController always shows current WKWebView instead of iFrame content
我有两个网页:/invoice_display
,其中显示发票并有一个 "Print" 按钮。 "Print" 按钮创建一个隐藏的 iFrame 并将源设置为 /invoice_printable
,它有一个 window.print()
嵌入在页面加载时执行的页面中。
这在网络浏览器中运行良好,但在 iOS 上加载 WKWebView
时遇到问题。问题是 UIPrintInteractionController
预览总是显示 /invoice_display
而不是 /invoice_printable
。
这是当前代码:
/invoice_printable
<script type="text/javascript">
window.onload = function () {
window.print();
}
</script>
UIViewController
- (void)createWebView {
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserScript *script = [[WKUserScript alloc] initWithSource:@"window.print = function() { window.webkit.messageHandlers.print.postMessage('print') }"
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:NO];
[config.userContentController addUserScript:script];
[config.userContentController addScriptMessageHandler:self name:@"print"];
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
webView.navigationDelegate = self;
webView.UIDelegate = self;
[self.view addSubview:webView];
self.webView = webView;
}
- (void)printCurrentPage {
UIPrintInteractionController *printInteractionController = [UIPrintInteractionController sharedPrintController];
printInteractionController.printFormatter = self.webView.viewPrintFormatter;
UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if (!completed) {
if (error) {
NSLog(@"Print failed: %@", error);
} else {
NSLog(@"Print cancelled");
}
}
};
[printInteractionController presentAnimated:YES completionHandler:completionHandler];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"print"]) {
NSLog(@"Got a 'print' message from the web page");
[self printCurrentPage];
} else {
NSLog(@"Got a web page message other than 'print'");
}
}
如何让可打印的 iFrame 内容显示在 UIPrintInteractionController
而不是原始网页中?
我想出了一个解决办法。我正在使用 webView:decidePolicyForNavigationAction:decisionHandler:
来检测 iFrame。然后,我使用 iFrame 的 NSURLRequest
获取网页 NSData
,然后将其作为 NSString
传递到 UIMarkupTextPrintFormatter
。最后,该格式化程序被传递给 UIPrintInteractionController
。呼。
这是工作代码:
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if (!navigationAction.targetFrame.isMainFrame) {
NSLog(@"Got an iFrame: %@", navigationAction.request.URL.absoluteString);
// Save this request so we can use it later for invoice printing
self.printRequest = navigationAction.request;
decisionHandler(WKNavigationActionPolicyAllow);
}
}
然后一旦网页调用 window.print()
...
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"print"]) {
NSLog(@"Got a 'print' message from the web page");
[self GETWebDataWithRequest:self.printRequest];
} else {
NSLog(@"Got a web page message other than 'print'");
}
}
- (void)GETWebDataWithRequest:(NSURLRequest *)request {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:nil delegateQueue:nil];
NSURLSessionDataTask *getDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(!error) {
NSLog(@"Got web data for url: %@", request.URL);
dispatch_async(dispatch_get_main_queue(), ^{
[self printCurrentPageWithData:data];
});
} else {
NSLog(@"Web data error: %@", error);
}
}];
[getDataTask resume];
}
- (void)printCurrentPageWithData:(NSData *)webData {
NSString *htmlString = [[NSString alloc] initWithData:webData encoding:NSUTF8StringEncoding];
UIMarkupTextPrintFormatter *markupTextPrintFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:htmlString];
UIPrintInteractionController *printInteractionController = [UIPrintInteractionController sharedPrintController];
printInteractionController.printFormatter = markupTextPrintFormatter;
UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if (!completed) {
if (error) {
NSLog(@"Print failed: %@", error);
} else {
NSLog(@"Print cancelled");
}
}
};
}
我有两个网页:/invoice_display
,其中显示发票并有一个 "Print" 按钮。 "Print" 按钮创建一个隐藏的 iFrame 并将源设置为 /invoice_printable
,它有一个 window.print()
嵌入在页面加载时执行的页面中。
这在网络浏览器中运行良好,但在 iOS 上加载 WKWebView
时遇到问题。问题是 UIPrintInteractionController
预览总是显示 /invoice_display
而不是 /invoice_printable
。
这是当前代码:
/invoice_printable
<script type="text/javascript">
window.onload = function () {
window.print();
}
</script>
UIViewController
- (void)createWebView {
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserScript *script = [[WKUserScript alloc] initWithSource:@"window.print = function() { window.webkit.messageHandlers.print.postMessage('print') }"
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:NO];
[config.userContentController addUserScript:script];
[config.userContentController addScriptMessageHandler:self name:@"print"];
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
webView.navigationDelegate = self;
webView.UIDelegate = self;
[self.view addSubview:webView];
self.webView = webView;
}
- (void)printCurrentPage {
UIPrintInteractionController *printInteractionController = [UIPrintInteractionController sharedPrintController];
printInteractionController.printFormatter = self.webView.viewPrintFormatter;
UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if (!completed) {
if (error) {
NSLog(@"Print failed: %@", error);
} else {
NSLog(@"Print cancelled");
}
}
};
[printInteractionController presentAnimated:YES completionHandler:completionHandler];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"print"]) {
NSLog(@"Got a 'print' message from the web page");
[self printCurrentPage];
} else {
NSLog(@"Got a web page message other than 'print'");
}
}
如何让可打印的 iFrame 内容显示在 UIPrintInteractionController
而不是原始网页中?
我想出了一个解决办法。我正在使用 webView:decidePolicyForNavigationAction:decisionHandler:
来检测 iFrame。然后,我使用 iFrame 的 NSURLRequest
获取网页 NSData
,然后将其作为 NSString
传递到 UIMarkupTextPrintFormatter
。最后,该格式化程序被传递给 UIPrintInteractionController
。呼。
这是工作代码:
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if (!navigationAction.targetFrame.isMainFrame) {
NSLog(@"Got an iFrame: %@", navigationAction.request.URL.absoluteString);
// Save this request so we can use it later for invoice printing
self.printRequest = navigationAction.request;
decisionHandler(WKNavigationActionPolicyAllow);
}
}
然后一旦网页调用 window.print()
...
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"print"]) {
NSLog(@"Got a 'print' message from the web page");
[self GETWebDataWithRequest:self.printRequest];
} else {
NSLog(@"Got a web page message other than 'print'");
}
}
- (void)GETWebDataWithRequest:(NSURLRequest *)request {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:nil delegateQueue:nil];
NSURLSessionDataTask *getDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(!error) {
NSLog(@"Got web data for url: %@", request.URL);
dispatch_async(dispatch_get_main_queue(), ^{
[self printCurrentPageWithData:data];
});
} else {
NSLog(@"Web data error: %@", error);
}
}];
[getDataTask resume];
}
- (void)printCurrentPageWithData:(NSData *)webData {
NSString *htmlString = [[NSString alloc] initWithData:webData encoding:NSUTF8StringEncoding];
UIMarkupTextPrintFormatter *markupTextPrintFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:htmlString];
UIPrintInteractionController *printInteractionController = [UIPrintInteractionController sharedPrintController];
printInteractionController.printFormatter = markupTextPrintFormatter;
UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if (!completed) {
if (error) {
NSLog(@"Print failed: %@", error);
} else {
NSLog(@"Print cancelled");
}
}
};
}