UIPrintInteractionController всегда показывает текущий WKWebView вместо содержимого iFrame - PullRequest
0 голосов
/ 30 мая 2019

У меня есть две веб-страницы: /invoice_display, которая показывает счет-фактуру и имеет кнопку «Печать». Кнопка «Печать» создает скрытый iFrame и устанавливает для источника значение /invoice_printable, в которое встроена window.print() страница, которая выполняется при загрузке страницы.

Все это прекрасно работает в веб-браузере, но у меня возникла проблема при загрузке в WKWebView на iOS. Проблема в том, что при предварительном просмотре 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 вместо исходной веб-страницы?

1 Ответ

0 голосов
/ 31 мая 2019

Я нашел решение.Я использую webView:decidePolicyForNavigationAction:decisionHandler: для обнаружения iFrame.Затем я использую iFrame NSURLRequest, чтобы получить веб-страницу как NSData, которую я затем передаю в UIMarkupTextPrintFormatter как NSString.Наконец, этот форматер передается в 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");
            }
        }
    };
}
...