如何打印所有WKWebView屏幕上和屏幕外的内容OSX和iOS

zqry0prt  于 2023-02-06  发布在  iOS
关注(0)|答案(7)|浏览(464)

**这个问题是关于打印WKWebView的所有内容(包括屏幕外内容)。**目前(仍然是iOS 10.2或OSX 10.12)没有有效的解决方案,Stackoverflow上的任何假设解决方案都不起作用。只有在您验证了可以打印屏幕外内容的情况下才能在这里提供答案,如果验证了,请提供工作示例代码。

我正尝试在OSX 10.10或更高版本(当前运行在10.11.2上)上打印WKWebViewWebView的***全部***内容。例如,一个宽的html表格,其中的列在视图之外并向右偏移。OSX的早期版本会自动分页并正确打印所有html。
我试过使用Stackoverflow和其他地方提供的解决方案,基本上都是这样打印documentView的:

[[NSPrintOperation printOperationWithView:_webView.mainFrame.frameView.documentView printInfo:pInfo] runOperation];

在10.10版本中,此操作对WKWebViewWebView均不起作用。如果执行此操作:

[[NSPrintOperation printOperationWithView:_wkWebView printInfo:pInfo] runOperation];

你得到分页,但打印输出包括滚动条WebView,另一个WKWebView给你空白页。
我在苹果文档中找不到任何关于在OSX上打印WKWebView的内容,也找不到任何OSX特定而非iOS的答案。
有人知道如何在OSX上打印这些吗?

更新:这是WebView中的一个错误**[Radar:23159060](仍在2018年2月开放),WKWebView甚至似乎没有解决OSX上的打印问题。在网上检查该类的开源后,我发现所有与打印有关的类都在一个条件编译块中,该块仅支持平台:iOS系统
更新第二部分:令人惊讶的是,这个荒谬的bug存在于这个类的所有实现中,包括iOS上的实现!我觉得荒谬的是,尽管文档中声明要使用这个,但这个
仍然在这么晚的时候没有修复(且仅限此类)。现在无法在iOS或OSX上打印WebView的所有屏幕上和屏幕外**内容。失败的苹果。是时候解决这个问题了!我们都知道史蒂夫会怎么说...
更新第三部分:)-然而更令人惊讶的是,这个问题并没有得到解决,因为10.15.2和未来4年以上!!!这个问题一直在浮动(苹果waaaaaake起来起来起来...).这是一种令人惊讶的考虑到他们越来越非常推动使用WKWebView和在iOS土地,甚至拒绝应用程序,不(除非你试图支持iOS 7).
更新第四部分(2020年......你能相信吗?!?):截至大苏尔,这仍然是一个问题。我解决了它写了一个工作周围见接受的答案如下:

printOperationWithPrintInfo:

不打印屏幕外或水平或垂直方向滚动到视图外的所有内容。但是它使用打印CSS,这比以下内容稍有优势:

- (void)takeSnapshotWithConfiguration:(WKSnapshotConfiguration *)snapshotConfiguration 
                completionHandler:(void (^)(NSImage *snapshotImage, NSError *error))completionHandler;

为了让它工作,我做了:

NSPrintInfo *pInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict];
pInfo.horizontalPagination = NSPrintingPaginationModeAutomatic;
pInfo.verticalPagination = NSPrintingPaginationModeAutomatic;
pInfo.verticallyCentered = YES;
pInfo.horizontallyCentered = YES;
pInfo.orientation = NSPaperOrientationLandscape;
pInfo.leftMargin = 30;
pInfo.rightMargin = 30;
pInfo.topMargin = 30;
pInfo.bottomMargin = 30;

NSPrintOperation *po = [_webView printOperationWithPrintInfo:pInfo];
po.showsPrintPanel = YES;
po.showsProgressPanel = YES;

// Without the next line you get an exception. Also it seems to
// completely ignore the values in the rect. I tried changing them
// in both x and y direction to include content scrolled off screen.
// It had no effect whatsoever in either direction. 
po.view.frame = _webView.bounds; 

// [printOperation runOperation] DOES NOT WORK WITH WKWEBVIEW, use 
[po runOperationModalForWindow:self.view.window delegate:self didRunSelector:@selector(printOperationDidRun:success:contextInfo:) contextInfo:nil];

**还有一点我不太明白。wkWebView的大小似乎并不重要。如果我调整应用程序的大小以隐藏一些内容,它似乎仍然会抓取屏幕外的内容,以适合指定的页面。但它似乎不知道如何将不适合页面大小的内容分页到其他页面上,所以这似乎是问题所在。可能有一些办法绕过这一点,如果有人有线索张贴在这里!!

vxf3dgd4

vxf3dgd41#

这不是正确答案,因为Apple需要通过有效的打印方法或.evaluateJavaScript("window.print()", completionHandler: nil)提供正确答案
但我有一个愚蠢的解决方案,“工程”为我,也许它会帮助其他人与工作左右,直到那时。
第一步:获取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: "")

    }

如果苹果能解决这个问题,那就太好了。我有一个内部应用程序,它用HTML做所有的报告,报告是你想打印的东西。

xmakbtuz

xmakbtuz2#

这是在macOS 11+中从WKWebView打印内容的基本实现。您将需要一个保留在内存中的类,因为您必须使用异步调用。使您的类符合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
}
nx7onnlm

nx7onnlm3#

我已经用尽了所有可能的方法来直接打印WKWebView,但没有成功。我能想到的唯一解决方法是将网页转换为PDF对象,然后打印该对象。如果解决方法有效,我将更新代码。

vyu0f0g1

vyu0f0g14#

在iOS中,我将UIView.viewPrintFormatter()传递给UIActivityViewController以允许用户打印所有内容

let myShare = [webView.viewPrintFormatter()]
let avc = UIActivityViewController(activityItems: myShare, applicationActivities: nil)

present(avc, animated: true, completion: nil)
a7qyws3x

a7qyws3x5#

这是我的@Altimac解决方案的快速版本(针对OSX 11更新)。

@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)
    }
}

至少对我有用。

h5qlskok

h5qlskok6#

我已成功使用SPI -[WKWebView _printOperationWithPrintInfo:]传递通常的[NSPrintInfo sharedPrintInfo]。请注意,您不能在返回的NSPrintOperation上使用-runOperation。您 * 必须 * 使用-runOperationModalForWindow:...,这非常类似。问题存在于WebKit内部,该内部期望运行runloop和内部预览以了解页数。
如果你所说的屏幕外是指“没有完全显示在屏幕上”的话,它肯定可以处理屏幕外的内容。我仍然有一个WKWebView显示在窗口中,但是它非常小,只显示了整个WebView内容(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
gkn4icbw

gkn4icbw7#

5年后,我设法解决了最初的问题,这是由WKWebViewprintOperationWithPrintInfoMacOS 11实现仍然不能正确处理滚动出视图并向右滚动的内容这一事实所迫使的。
根本问题似乎是剪辑区域边界之外的内容(尤其是右边)没有得到正确处理,这可能是WKWebView的bug,因为它似乎处理了垂直方向上可见矩形下方的一些内容。
经过深入研究,发现其他人已经能够打印NSView的全部内容并正确分页,方法是:

  • 视图分离(不在屏幕上)。
  • 将框架设置为整个内容的大小。
  • 然后在分离视图上调用printWithPrintInfo

我想到了一个解决办法
1.通过一个类别扩展WKWebView,它可以通过JavaScript在MacOS上获取所有内容,在iOS上通过操作与WKWebView关联的UIScrollView获取完整的内容大小,然后将内容的各个部分滚动到可见区域,并将其快照为图像块网格。
1.创建一个NSView or UIView的子类,以正确的关系绘制所有图块。
1.在分离视图上调用printWithPrintInfo

在MacOS 10.14+ iOS 13+上运行良好

在这两个平台上,所有输出都正确分页(iOS需要使用UIPrintPageRenderer,它包含在相关的GitHub项目中),您可以在预览中使用打开为PDF并将其保存为文件等。
我遇到的唯一缺点是没有使用打印CSS,考虑到苹果目前对打印CSS的支持很小,这并不重要。
所有工作代码都在GitHub上:Full working source for iOS and 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

用法

在任何处理WKWebView打印的地方使用Category,如下所示:

-(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的代码:Above code
WKWebView开始,内容如下,并向右滚动:

用户可以得到正确分页的打印对话框:

相关问题