如何一次性 AirPrint 多个打印格式化程序?
How to AirPrint multiple print formatters in one go?
我的最终目标是创建多个 UIMarkupTextPrintFormatter
并将它们全部打印在一个打印作业中。
例如,第一个格式化程序包含的文本填满了第一页和第二页的一点点。虽然还剩下 space 打印第二个格式化程序,但我希望第二个格式化程序打印在第三页上。所以基本上,在打印另一个格式化程序之前,开始一个新页面。
我不知道一个格式化程序在编译时会填满多少页,因为它取决于用户输入。可能是 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)
}
}
但是当打印交互控制器显示时它就崩溃了:
Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
我的代码哪里做错了?
根据文档看来,UIPrintFormatter 在计算要以格式打印的页数之前需要所有信息。
UIPrintFormatter publishes an interface that allows you to specify the
starting page for a print job and the margins around the printed
content; given that information plus the content, a print formatter
computes the number of pages for the print job.
所以除非 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
希望对您有所帮助。
我的最终目标是创建多个 UIMarkupTextPrintFormatter
并将它们全部打印在一个打印作业中。
例如,第一个格式化程序包含的文本填满了第一页和第二页的一点点。虽然还剩下 space 打印第二个格式化程序,但我希望第二个格式化程序打印在第三页上。所以基本上,在打印另一个格式化程序之前,开始一个新页面。
我不知道一个格式化程序在编译时会填满多少页,因为它取决于用户输入。可能是 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)
}
}
但是当打印交互控制器显示时它就崩溃了:
Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
我的代码哪里做错了?
根据文档看来,UIPrintFormatter 在计算要以格式打印的页数之前需要所有信息。
UIPrintFormatter publishes an interface that allows you to specify the starting page for a print job and the margins around the printed content; given that information plus the content, a print formatter computes the number of pages for the print job.
所以除非 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
希望对您有所帮助。