Как распечатать все WKWebView на и закадровый контент OSX и iOS
Этот вопрос касается печати ВСЕГО содержимого (включая закадровое содержимое) WKWebView. В настоящее время (по-прежнему, в iOS 10.2 или OSX 10.12) нет НИКАКОГО рабочего решения, и ни одно из предполагаемых решений по Stackru не работает. Ответ здесь предоставляется только в том случае, если вы сами убедились, что можете печатать СОДЕРЖАНИЕ ЭКРАНА ОТКЛ, и если вы это сделали, то предоставьте рабочий пример кода.
Я пытаюсь напечатать ВСЕ содержимое WKWebView или WebView на OSX 10.10 или выше (в настоящее время работает на 10.11.2). Например, широкая HTML-таблица, где столбцы не видны и расположены справа. Более ранние версии OSX автоматически разбивали на страницы и правильно печатали все html.
Я пытался использовать решения, доступные здесь, в Stackru и в других местах. Все по сути говорят то же самое, что печатать documentView
вот так:
[[NSPrintOperation printOperationWithView:_webView.mainFrame.frameView.documentView printInfo:pInfo] runOperation];
Это перестало работать как для WKWebView, так и для WebView в 10.10. Если вы делаете это:
[[NSPrintOperation printOperationWithView:_wkWebView printInfo:pInfo] runOperation];
Вы получаете нумерацию страниц, но распечатка включает полосы прокрутки WebView
, и другие WKWebView
дает вам пустые страницы.
Я не могу найти никаких упоминаний в документации Apple о печати для WKWebView на OSX. Также я не могу найти ответ, который относится к OSX, а не к iOS.
У кого-нибудь есть идеи, как распечатать их на OSX?
ОБНОВЛЕНИЕ: Это ошибка в WebView [Radar: 23159060] (по-прежнему открыт 2/2018), и WKWebView даже не отображается для печати в OSX. Изучив Open Source для этого класса в сети, я вижу, что все классы, имеющие отношение к печати, находятся в блоке условной компиляции, который поддерживает только платформу: iOS.
ОБНОВЛЕНИЕ Part Deux: Удивительно, что эта нелепая ошибка существует во ВСЕХ реализациях этого класса, в том числе и на iOS! Мне кажется смешным, что это все еще не исправлено в столь позднюю дату, несмотря на заявление документации об использовании этого (и только этого класса) в приложениях, поддерживающих iOS 8 или выше. Теперь НЕВОЗМОЖНО печатать все содержимое WebView на экране и вне экрана на iOS или OSX. Сбой Apple. Время исправить это! Мы все знаем, что Стив сказал бы по этому поводу...
Примечание. Кроме того, я считаю, что основной причиной этой проблемы является то, что также делает невозможным сохранение ВСЕГО содержимого WKWebView в виде изображения. Раньше были некоторые методы, которые можно было использовать с UIWebView для сохранения всего изображения на экране и вне экрана WebView в изображение. Я еще не нашел рабочее решение.
8 ответов
Через 5 лет я сумел решить исходную задачу и который вынужден был тем фактом , что MacOS 11 реализации
printOperationWithPrintInfo
по-прежнему не обрабатывает должным образом контент, прокрученный вне поля зрения и вправо.
Основная проблема, по-видимому, в том, что контент за пределами области отсечения (особенно справа) не обрабатывается должным образом. Это может быть ошибкой, поскольку кажется, что он обрабатывает некоторый контент ниже видимого прямоугольника в вертикальном направлении.
После долгих поисков и наблюдения за тем, что другие смогли получить все содержание
NSView
для печати и правильной разбивки на страницы, имея:
- Вид отдельно (не на экране).
- Установка рамки по размеру всего содержимого.
- Затем вызываем printWithPrintInfo в отдельном представлении.
У меня была идея решения:
- Расширьте с помощью категории с функциями, которые получают весь контент в виде фрагментов изображения. Он делает это в MacOS через JavaScript и в iOS, манипулируя
UIScrollView
связаны с, чтобы получить полный размер содержимого, а затем прокрутить различные части содержимого в видимую область и сделать снимок в виде сетки фрагментов изображения. - Создайте подкласс
NSView or UIView
который рисует все плитки в их правильном соотношении. - Вызов
printWithPrintInfo
на сторонний взгляд.
Хорошо работает на MacOS 10.14+ iOS 13+
На обеих платформах весь вывод правильно разбивается на страницы (iOS требует использования UIPrintPageRenderer, который включен в связанный проект GitHub), и вы можете использовать открытый как PDF в предварительном просмотре и сохранить его как файл и т. Д.
Единственный недостаток, с которым я столкнулся, заключается в том, что Print CSS НЕ используется, что не имеет большого значения, учитывая, что поддержка Apple для Print CSS в настоящее время минимальна.
Весь рабочий код находится на GitHub здесь: Полный рабочий исходный код для iOS и MacOS
ЭТОТ источник устарел См. Github
Заголовок
//
// WKWebView+UtilityFunctions.h
// Created by Clifford Ribaudo on 12/24/20.
//
#import <WebKit/WebKit.h>
#ifdef _MAC_OS_ // Up to user to determine how they know this
#define IMAGE_OBJ NSImage
#define VIEW_OBJ NSView
#else
#define IMAGE_OBJ UIImage
#define VIEW_OBJ UIView
#endif
@interface TiledImageView : VIEW_OBJ
{
NSArray *_imageTiles;
}
-(void)printWithPrintInfo:(NSPrintInfo *)pi;
-(instancetype)initWithFrame:(CGRect)frame imageTiles:(NSArray<NSArray *> *)imageTiles;
@end
@interface WKWebView (UtilityFunctions)
-(void)HTMLPageMetrics:(void (^)(CGSize htmlDocSize, CGSize visibleSize, NSError *error))completionHandler;
-(void)currentScrollXY:(void (^)(float x, float y, NSError *error))completionHandler;
-(void)scrollHTMLTo:(float)x topY:(float)y completionHandler:(void (^)(NSError *error))completionHandler;
-(void)imageTilesForHTMLPage:(CGSize)pageSize visbleRect:(CGSize)visibleRect imgData:(NSMutableArray<NSArray *> *)tileData completionHandler:(void (^)(NSError *error))completionHandler;
-(void)imageTile:(CGRect)imgRect fromPageOfSize:(CGSize)pageSize inViewOfSize:(CGSize)viewSize completionHandler:(void (^)(IMAGE_OBJ *tileImage, NSError *error))completionHandler;
@end
Реализация
//
// WKWebView+UtilityFunctions.m
// Created by Clifford Ribaudo on 12/24/20.
//
// Works with MacOS v10.14+ and ??iOS 13+
//
#import "WKWebView+UtilityFunctions.h"
@implementation TiledImageView
-(instancetype)initWithFrame:(CGRect)frame imageTiles:(NSArray<NSArray *> *)imageTiles
{
self = [super initWithFrame:NSRectFromCGRect(frame)];
if(self) {
_imageTiles = imageTiles;
}
return self;
}
-(BOOL)isFlipped {return YES;}
-(void)printWithPrintInfo:(NSPrintInfo *)pi
{
NSPrintOperation *po = [NSPrintOperation printOperationWithView:self];
po.printInfo = pi;
[po runOperation];
}
- (void)drawRect:(NSRect)rect
{
for(NSArray *imgData in _imageTiles)
{
NSRect drawRect = ((NSValue *)imgData[0]).rectValue;
IMAGE_OBJ *img = imgData[1];
[img drawInRect:drawRect];
}
}
@end
@implementation WKWebView (UtilityFunctions)
//
// Returns via Completion Handler:
// htmlDocSize - The size of the entire <HTML> element, visible or not
// visibleSize - The visible dimensions of the page, essentially WKWebView bounds minus HTML scroll bar dimensions
//
-(void)HTMLPageMetrics:(void (^)(CGSize htmlDocSize, CGSize visibleSize, NSError *error))completionHandler
{
//
// Anonymous Function - gets Size of entire HTML element and visible size.
// Result String = Full X, Full Y, Visible X, Visible Y
//
NSString *jsGetPageMetrics = @"(function(){return document.documentElement.scrollWidth + ',' + document.documentElement.scrollHeight + ',' + document.documentElement.clientWidth + ',' +document.documentElement.clientHeight;})();";
// Execute JS in WKWebView
[self evaluateJavaScript:jsGetPageMetrics completionHandler:^(id result, NSError *error)
{
CGSize htmlSize = CGSizeMake(0, 0);
CGSize visibleSize = CGSizeMake(0, 0);
if(!error && result)
{
NSArray<NSString *> *data = [[NSString stringWithFormat:@"%@", result] componentsSeparatedByString:@","];
htmlSize = CGSizeMake([data[0] floatValue], [data[1] floatValue]);
visibleSize = CGSizeMake([data[2] floatValue], [data[3] floatValue]);
}
else
NSLog(@"JS error getting page metrics: %@", error.description);
completionHandler(htmlSize, visibleSize, error);
}];
}
//
// Get <HTML> element current scroll position (x,y) and return to completeion handler:
// x = document.documentElement.scrollLeft
// y = document.documentElement.scrollTop
//
-(void)currentScrollXY:(void (^)(float X, float Y, NSError *error))completionHandler
{
NSString *jsGetPageMetrics = @"(function(){return document.documentElement.scrollLeft + ',' + document.documentElement.scrollTop;})();";
// Execute JS in WKWebView
[self evaluateJavaScript:jsGetPageMetrics completionHandler:^(id result, NSError *error) {
if(!error && result)
{
NSArray<NSString *> *data = [[NSString stringWithFormat:@"%@", result] componentsSeparatedByString:@","];
completionHandler([data[0] floatValue], [data[1] floatValue], error);
}
else {
NSLog(@"JS error getting page metrics: %@", error.localizedDescription);
completionHandler(0, 0, error);
}
}];
}
//
// Scroll the current HTML page to x, y using scrollTo(x,y) on the <HTML> element
// Optional Completion Handler to do something when scroll finished
//
-(void)scrollHTMLTo:(float)x topY:(float)y completionHandler:(void (^)(NSError *error))completionHandler
{
NSString *js = [NSString stringWithFormat:@"document.documentElement.scrollTo(%0.f, %0.f);", x, y];
// Execute JS in WKWebView
[self evaluateJavaScript:js completionHandler:^(id result, NSError *error)
{
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, .25 * NSEC_PER_SEC);
dispatch_after(delay, dispatch_get_main_queue(), ^{
if(completionHandler) completionHandler(error);
});
if(error) NSLog(@"JS error scrollTo %@", error.localizedDescription);
}];
}
//
// Called Recursively until tiles are obtained for the entire pageRect.
// Tiles are the size of visibleRect (WKWebView.bounts) but can be smaller.
// tileData - Array of arrays holding CGRect & Img.
//
-(void)imageTilesForHTMLPage:(CGSize)pageSize visbleRect:(CGSize)visibleSize imgData:(NSMutableArray<NSArray *> *)tileData completionHandler:(void (^)(NSError *error))completionHandler
{
__block CGRect currentRect; // In coordinates of pageSize (full).
if(tileData.count == 0) { // No image tiles yet. Start at top left of html page for visible WKWebView bounds
currentRect.origin.x = currentRect.origin.y = 0.0;
currentRect.size = visibleSize;
}
else {
NSArray *lastTile = [tileData lastObject]; // Calculate what the next tile rect is or call handler if done.
CGRect lastTileRect;
#ifdef _MAC_OS_
lastTileRect = ((NSValue *)lastTile[0]).rectValue;
#else
lastTileRect = ((NSValue *)lastTile[0]).CGRectValue;
#endif
// Check if anything more to get to right of last tile
if((lastTileRect.origin.x + lastTileRect.size.width) < pageSize.width)
{
currentRect.origin.x = lastTileRect.origin.x + lastTileRect.size.width + 1; // Next x to right of last tile
currentRect.origin.y = lastTileRect.origin.y; // Works on all rows
currentRect.size.height = lastTileRect.size.height;
currentRect.size.width = pageSize.width - currentRect.origin.x; // Get width of next tile to right of last
if(currentRect.size.width > visibleSize.width) // If more tiles to right use visible width
currentRect.size.width = visibleSize.width;
}
else if((lastTileRect.origin.y + lastTileRect.size.height) < pageSize.height) // New Row
{
currentRect.origin.x = 0; // Reset x back to left side of hmtl
currentRect.size.width = visibleSize.width; // Reset width back to view width
currentRect.origin.y = lastTileRect.origin.y + lastTileRect.size.height + 1; // Get y below last row
currentRect.size.height = pageSize.height - currentRect.origin.y;
if(currentRect.size.height > visibleSize.height) // If more rows below use row height
currentRect.size.height = visibleSize.height;
}
else {
completionHandler(nil);
return;
}
}
[self imageTile:currentRect fromPageOfSize:pageSize inViewOfSize:visibleSize completionHandler:^(NSImage *tileImage, NSError *error)
{
if(error || !tileImage) {
NSLog(@"Error getting image tiles %@", error.description);
completionHandler(error);
return;
}
#ifdef _MAC_OS_
[tileData addObject:@[[NSValue valueWithRect:NSRectFromCGRect(currentRect)], tileImage]];
#else
[tileData addObject:@[[NSValue valueWithCGRect:currentRect], tileImage]];
#endif
[self imageTilesForHTMLPage:(CGSize)pageSize visbleRect:(CGSize)visibleSize imgData:(NSMutableArray<NSArray *> *)tileData completionHandler:completionHandler];
}];
}
//
// ImgRect = location of rect in full page size. Has to be translated into what is visible and where.
// pageSize = Full size of HTML page, visible or not.
// viewSize = essentially the wkwebview.bounds.size - HTML scroll bars.
//
-(void)imageTile:(CGRect)imgRect fromPageOfSize:(CGSize)pageSize inViewOfSize:(CGSize)viewSize completionHandler:(void (^)(IMAGE_OBJ *tileImage, NSError *error))completionHandler
{
float x = imgRect.origin.x; // Always do this to make the desired rect visible in the rect of viewSize
float y = imgRect.origin.y;
CGRect rectToGetFromView;
rectToGetFromView.origin.x = 0;
rectToGetFromView.origin.y = 0;
rectToGetFromView.size = imgRect.size;
// If img is smaller than the viewport, determine where it is after scroll
if(imgRect.size.width < viewSize.width)
rectToGetFromView.origin.x = viewSize.width - imgRect.size.width;
if(imgRect.size.height < viewSize.height)
rectToGetFromView.origin.y = viewSize.height - imgRect.size.height;
[self scrollHTMLTo:x topY:y completionHandler:^(NSError *error)
{
if(!error) {
WKSnapshotConfiguration *sc = [WKSnapshotConfiguration new];
sc.rect = rectToGetFromView;
[self takeSnapshotWithConfiguration:sc completionHandler:^(IMAGE_OBJ *img, NSError *error)
{
if(error) NSLog(@"Error snapshotting image tile: %@", error.description);
completionHandler(img, error);
}];
}
else {
NSLog(@"Error scrolling for next image tile %@", error.description);
completionHandler(nil, error);
}
}];
}
@end
Применение
Используйте категорию в любых ручках печати, например:
-(void)print:(id)sender
{
// Set this as per your needs
NSPrintInfo *pInfo = [NSPrintInfo sharedPrintInfo];
pInfo.verticallyCentered = YES;
pInfo.horizontallyCentered = NO;
pInfo.horizontalPagination = NSAutoPagination;
pInfo.verticalPagination = NSAutoPagination;
pInfo.orientation = NSPaperOrientationLandscape;
pInfo.bottomMargin = 30;
pInfo.topMargin = 30;
pInfo.leftMargin = 30;
pInfo.rightMargin = 30;
pInfo.scalingFactor = .60;
[_webView HTMLPageMetrics:^(CGSize htmlSize, CGSize visibleSize, NSError *error)
{
self->_imgTileData = [NSMutableArray new];
[self->_webView imageTilesForHTMLPage:htmlSize visbleRect:visibleSize imgData:self->_imgTileData completionHandler:^(NSError *error) {
if(!error) {
TiledImageView *tiv = [[TiledImageView alloc] initWithFrame:CGRectMake(0,0,htmlSize.width,htmlSize.height) imageTiles:self->_imgTileData];
[tiv printWithPrintInfo:pInfo];
}
}];
}
}
Вот код в виде Github Gist: Над кодом
И от этого
WKWebView
с содержимым ниже, а также с прокруткой вправо:
Получается этот диалог печати с правильной разбивкой на страницы:
ПРИМЕЧАНИЕ от OP: это решение имеет ту же проблему, которая существует уже довольно долгое время. Если вы используете неопубликованный метод и игнорируете выдаваемые ошибки и устанавливаете поля, размер бумаги и следующие флаги в NSPrintInfo:orientation = NSPaperOrientationLandscape
а также horizontalPagination = NSPrintingPaginationModeAutomatic
, результат такой же, как и в течение некоторого времени, и отображается диалоговое окно печати, а предварительный просмотр печати имеет ТОЛЬКО 1 страницу, и на которой отсутствует содержимое справа. WKWebView не понимает, как разбить контент на страницы вправо.
Возможно, стоит изучить решение, создав подкласс WKWebView и переопределив knowsPageRange:
и некоторые другие методы печати для View. Также это может работать в вертикальном направлении. Я не пробовал этого, так как мой вариант использования - это необходимость правильно разбивать страницы по горизонтали с содержимым HTML в столбцах TABLE, слишком далеко вправо, чтобы поместиться на одной странице. Вышеупомянутые настройки DID использовались для работы в классе WebView, а затем впоследствии сломались как в WebView, так и в WKWebView - Конец ПРИМЕЧАНИЕ от OP
Я успешно использовал SPI -[WKWebView _printOperationWithPrintInfo:], передав обычный [NSPrintInfo sharedPrintInfo]. Обратите внимание, что вы НЕ МОЖЕТЕ использовать -runOperation для возвращенного NSPrintOperation. Вы должны использовать -runOperationModalForWindow:...., что очень похоже. Проблема заключается во внутреннем устройстве WebKit, которое ожидает, что будет запущен цикл выполнения и будет выполнен предварительный просмотр, чтобы узнать количество страниц.
Это определенно работает с содержимым вне экрана, если то, что вы имеете в виду под неэкранным контентом, "не полностью отображается на экране". У меня все еще отображается WKWebView в окне, но он очень крошечный и отображает только очень небольшую часть всего содержимого веб-просмотра (21 страница A4!). Надеюсь это поможет!
PS: Проверено 10.12, 10.14 и 10.15. Код такой:
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
Решение, которое я использую, состоит в том, чтобы создать экземпляр старого доброго объекта WebView и использовать метод печати этого объекта.
class WebPrinter: NSObject, WebFrameLoadDelegate {
let window: NSWindow
var printView: WebView?
let printInfo = NSPrintInfo.shared
init(window: NSWindow) {
self.window = window
printInfo.topMargin = 30
printInfo.bottomMargin = 15
printInfo.rightMargin = 0
printInfo.leftMargin = 0
}
func printHtml(_ html: String) {
let printViewFrame = NSMakeRect(0, 0, printInfo.paperSize.width, printInfo.paperSize.height)
printView = WebView(frame: printViewFrame, frameName: "printFrame", groupName: "printGroup")
printView!.shouldUpdateWhileOffscreen = true
printView!.frameLoadDelegate = self
printView!.mainFrame.loadHTMLString(html, baseURL: Bundle.main.resourceURL)
}
func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
if sender.isLoading {
return
}
if frame != sender.mainFrame {
return
}
if sender.stringByEvaluatingJavaScript(from: "document.readyState") == "complete" {
sender.frameLoadDelegate = nil
let printOperation = NSPrintOperation(view: frame.frameView.documentView, printInfo: printInfo)
printOperation.runModal(for: window, delegate: window, didRun: nil, contextInfo: nil)
}
}
}
Это не правильный ответ, потому что Apple должна предоставить правильный ответ с рабочим методом печати или .evaluateJavaScript("window.print()", completionHandler: nil)
Но у меня есть глупое решение, которое "работает" для меня, и, возможно, оно поможет другим людям обойтись до тех пор.
Шаг 1: Возьмите HTML и исправьте <body> tag with <body onload='window.print()'>
, Если вы извлекаете html из какого-либо места и не загружаете свой собственный, вам нужно использовать некоторые регулярные выражения. Я не буду вдаваться в это.
Шаг 2: Сохраните HTML-файл в файле и сохраните полный путь в переменной. В моем примере: имя файла
Шаг 3: Подключите кнопку печати к этому коду:
RunCommand(command: "/usr/bin/open \(filename)")
Смотрите код для RunCommand ниже. Это оставляет тупое окно Safari, но позволяет напечатать что-то без сохранения в файл, а затем вспомнить, куда вы его вставили, чтобы вы могли открыть его в Safari самостоятельно для печати.
func RunCommand(command: String) -> (success: Bool, result: String) {
let cc = command.components(separatedBy: " ")
let process = Process()
process.launchPath = cc[0]
var cp: [String] = []
for i in (1..<cc.count) {
cp.append(cc[i])
}
process.arguments = cp
let pipe = Pipe()
process.standardOutput = pipe
process.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
if (data.count > 0) {
let output = String(data: data, encoding: String.Encoding.utf8)
// let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
return (success: true, result: output!)
}
return (success: true, result: "")
}
Было бы здорово, если бы Apple смогла это исправить. У меня есть собственное приложение, которое выполняет все свои отчеты в формате HTML, а отчеты - это то, что вы хотите напечатать.
Это базовая реализация печати содержимого изWKWebView
в macOS 11+. Вам понадобится класс, который сохраняется в памяти, потому что вам придется использовать асинхронные вызовы. Сделайте так, чтобы ваш класс соответствовалWKNavigationDelegate
поймать, когда контент был загружен.
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[webView display];
[self exportPDFtoURL:tempURL];
}
- (void)exportPDFtoURL:(NSURL*)url forPreview:(bool)preview {
// Save the url for asynchronous callback
self.pdfURL = url;
NSPrintInfo *printInfo = NSprintInfo.sharedPrintInfo;
[printInfo.dictionary addEntriesFromDictionary:@{
NSPrintJobDisposition: NSPrintSaveJob,
NSPrintJobSavingURL: url
}];
NSPrintOperation *printOperation [(WKWebView*)_webView printOperationWithPrintInfo:printInfo];
printOperation.view.frame = NSMakeRect(0,0, printInfo.paperSize.width, printInfo.paperSize.height);
printOperation.showsPrintPanel = NO;
printOperation.showsProgressPanel = YES;
// Print the content and call a selector afterwards
[printOperation runOperationModalForWindow:self.window delegate:self didRunSelector:@selector(printOperationDidRun:success:contextInfo:) contextInfo:nil];
}
- (void)printOperationDidRun:(id)operation success:(bool)success contextInfo:(nullable void *)contextInfo {
// Remove WKWebView from memory
self.webView.navigationDelegate = nil;
[webView.configuration.userContentController removeAllUserScripts];
// Do something with the URL here
}
Я исчерпал все возможные способы печати WKWebView напрямую, но безуспешно. Единственный обходной путь, о котором я могу подумать, - это преобразовать веб-страницу в объект PDF, а затем распечатать указанный объект. Я обновлю код, если я найду обходной путь.
В iOS я передаю UIView.viewPrintFormatter() в UIActivityViewController, чтобы позволить пользователям печатать все
let myShare = [webView.viewPrintFormatter()]
let avc = UIActivityViewController(activityItems: myShare, applicationActivities: nil)
present(avc, animated: true, completion: nil)
это моя быстрая версия (обновленная для OSX 11) решения @Altimac.
@available(OSX 11.0, *)
extension BrowserViewController
{
func print(pdf: Bool)
{
guard var printInfoDictionary = NSPrintInfo.shared.dictionary().mutableCopy() as? [NSPrintInfo.AttributeKey: Any] else { return }
printInfoDictionary[NSPrintInfo.AttributeKey.jobDisposition] = pdf ? NSPrintInfo.JobDisposition.preview : NSPrintInfo.JobDisposition.spool
printInfoDictionary[NSPrintInfo.AttributeKey.detailedErrorReporting] = true
let printInfo = NSPrintInfo(dictionary: printInfoDictionary)
printInfo.horizontalPagination = .automatic
printInfo.verticalPagination = .automatic
printInfo.isVerticallyCentered = false
printInfo.isHorizontallyCentered = false
printInfo.leftMargin = 10
printInfo.rightMargin = 10
printInfo.topMargin = 10
printInfo.bottomMargin = 10
let printOperation = theWebView.printOperation(with: printInfo)
printOperation.showsPrintPanel = false
printOperation.showsProgressPanel = false
printOperation.runModal(for: self.view.window!, delegate: self, didRun: nil, contextInfo: nil)
}
}
похоже, по крайней мере, для меня работает.