【问题标题】:How to AirPrint multiple print formatters in one go?如何一次性 AirPrint 多个打印格式化程序?
【发布时间】:2016-12-06 08:03:13
【问题描述】:

我的最终目标是创建多个UIMarkupTextPrintFormatter 并将它们全部打印在一个打印作业中。

例如,第一个格式化程序包含填充第一页和第二页一点点的文本。虽然仍有空间打印第二个格式化程序,但我希望第二个格式化程序打印在第三页上。所以基本上,在打印另一个格式化程序之前,开始一个新页面。

我不知道一个格式化程序在编译时会填满多少页,因为它取决于用户输入。可能有 1 个、2 个或更多。

我听说我需要使用UIPrintPageRenderer,所以我阅读了它的文档并尝试了这个:

// I'm using webviews here because I don't want to write 2 pages worth of markup...
// it should be the same anyway. The two webviews display different wikipedia articles
// Also, don't judge my variable names. I'm lazy and this is just test code...
let formatter = webView.viewPrintFormatter()
let formatter1 = webView2.viewPrintFormatter()

formatter.contentInsets = UIEdgeInsets(top: 72, left: 72, bottom: 72, right: 72)
formatter1.contentInsets = UIEdgeInsets(top: 72, left: 72, bottom: 72, right: 72)

let renderer = UIPrintPageRenderer()
renderer.addPrintFormatter(formatter, startingAtPageAt: 0)
renderer.addPrintFormatter(formatter1, startingAtPageAt: formatter.pageCount)

printController.printPageRenderer = renderer
printController.present(animated: true, completionHandler: nil)

为了添加第二个打印格式化程序,我使用formatter.pageCount 作为第二个参数。我希望它会在第一页的最后一页之后添加第二个格式化程序。但它没有。它只打印了第二个格式化程序中的内容。

我打印了formatter.pageCount,发现它的值为0。

我完全糊涂了。如何获取格式化程序将填满多少页?

我也尝试实现自己的渲染器:

class MyRenderer: UIPrintPageRenderer {
    override func drawPrintFormatter(_ printFormatter: UIPrintFormatter, forPageAt pageIndex: Int) {
        printFormatter.draw(in: self.printableRect, forPageAt: pageIndex)
    }
}

但是当打印交互控制器显示时它就崩溃了:

试图从主线程或web线程以外的线程获取web lock。这可能是从辅助线程调用 UIKit 的结果。现在崩溃了...

我的代码做错了什么?

【问题讨论】:

  • 您正在从不是主线程的线程调用 UI 内容。您必须仅从主线程调用 UI 内容。显示您调用此代码的位置。可能来自下载任务的完成处理程序或 webview 的委托。
  • @shallowThought 我在 @IBAction 方法中执行此操作,该方法应该在 UI 线程上。
  • 没有看到真正的代码,很难甚至不可能提供帮助。
  • @shallowThought 所以你不能用给定的代码重现问题?我的代码可以在你的机器上运行吗?
  • 恐怕没有更真实的代码,这(复制)是不可能的。

标签: ios swift airprint


【解决方案1】:

按照文档看来,UIPrintFormatter 在计算以该格式打印的页数之前需要所有信息。

UIPrintFormatter 发布了一个接口,允许您指定 打印作业的起始页和打印件周围的边距 内容;给定这些信息加上内容,一个打印格式化程序 计算打印作业的页数。

所以这不会发生,除非 UIPrintFormatter 开始打印内容。

由于 UIPrintPageRenderer 可以使用 UIPrintFormatter 它实际上可以获得与格式化程序相关联的页面数,您所要做的就是覆盖 numberOfPages 以在每个页面设置不同的格式化程序。

以下是来自 Apple 的示例代码。完全相同的事情 - 在每个页面上附加多个格式化程序(UIMarkupTextPrintFormatter)。

它在这里覆盖 numberOfPages:

- (NSInteger)numberOfPages {
    self.printFormatters = nil;
    [self setupPrintFormatters];
    return [super numberOfPages];
}

并在此处将格式化程序附加到每个页面:

  /*
     Iterate through the recipes setting each of their html representations into 
     a UIMarkupTextPrintFormatter and add that formatter to the printing job.
     */
    - (void)setupPrintFormatters {
        NSInteger page = 0;
        CGFloat previousFormatterMaxY = CGRectGetMinY(self.contentArea);

        for (Recipe *recipe in recipes) {
            NSString *html = recipe.htmlRepresentation;

            UIMarkupTextPrintFormatter *formatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:html];
            [formatterToRecipeMap setObject:recipe forKey:formatter];

            // Make room for the recipe info
            UIEdgeInsets contentInsets = UIEdgeInsetsZero;
            contentInsets.top = previousFormatterMaxY + self.recipeInfoHeight;
            if (contentInsets.top > CGRectGetMaxY(self.contentArea)) {
                // Move to the next page
                page++;
                contentInsets.top = CGRectGetMinY(self.contentArea) + self.recipeInfoHeight;
            }
            formatter.contentInsets = contentInsets;

            // Add the formatter to the renderer at the specified page
            [self addPrintFormatter:formatter startingAtPageAtIndex:page];

            page = formatter.startPage + formatter.pageCount - 1;
            previousFormatterMaxY = CGRectGetMaxY([formatter rectForPageAtIndex:page]);

        }
    }

简而言之,它是根据内容区域、内容插入计算页码,然后通过调用 API 将格式化程序附加到页面:

 [self addPrintFormatter:formatter startingAtPageAtIndex:page];

这样,Renderer 就有了关于每个页面的格式化程序的信息。 你可以找到完整的代码here

希望它会有所帮助。

【讨论】:

  • 这是否会为每个格式化的打印开始一个新页面?
  • 好吧,如果我们检查你是否看到行 page = formatter.startPage + formatter.pageCount - 1;在这一行中,它实际上计算了格式化程序将保留多少页。然后在 for 循环的下一个循环中再次增加页数。
  • 我明白了。谢谢!我会试试这个。
  • 我试过了,它仍然说我在错误的线程上。我认为问题不是因为我使用了多个格式化程序。即使我使用一个简单的文本格式化程序,它似乎也会崩溃。因此,我想我会提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-19
  • 1970-01-01
  • 2015-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多