Has anyone tried using multiple formatters (UIViewPrintFormatter
, UIMarkupTextPrintFormatter
, UISimpleTextPrintFormatter
) with a page renderer (UIPrintPageRenderer
) to print the content?
I'm trying to use two UIMarkupTextPrintFormatters
with a UIPrintPageRenderer
subclass, but i'm failing to get the print. I'm using MyPrintPageRenderer
class from PrintWebView sample code.
I've gone through the Apple's documentation but it isn't very helpful, and there is no sample code associated with the description. I've tried a couple of solutions but so far I haven't had any success.
Any suggestions?
The fact that there is very little activity in the "Printing" section suggests that either not many people are using this, or people using this API are not visiting this community, or people are just ignoring the question for some reason.
Anyways, i was able to solve my problem. I was using setPrintFormatters:
method earlier which wasn't/isn't working. I don't know why. So, i started experimenting with addPrintFormatter:startingAtPageAtIndex:
method instead. And here's how i solved my problem:
// To draw the content of each page, a UIMarkupTextPrintFormatter is used.
NSString *htmlString = [self prepareWebViewHTML];
UIMarkupTextPrintFormatter *htmlFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:htmlString];
NSString *listHtmlString = [self prepareWebViewListHTMLWithCSS];
UIMarkupTextPrintFormatter *listHtmlFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:listHtmlString];
// I think this should work, but it doesn't! The result is an empty page with just the header and footer text.
// [myRenderer setPrintFormatters:[NSArray arrayWithObjects:htmlFormatter, listHtmlFormatter, nil]];
// Alternatively, i've used addPrintFormatters here, and they just work!
// Note: See MyPrintPageRenderer's numberOfPages method implementation for relavent details.
// The important point to note there is that the startPage property is updated/corrected.
[myRenderer addPrintFormatter:htmlFormatter startingAtPageAtIndex:0];
[myRenderer addPrintFormatter:listHtmlFormatter startingAtPageAtIndex:1];
In the MyPrintPageRenderer
, i used following code to update/correct the startPage property so that a new page is used for each formatter:
- (NSInteger)numberOfPages
{
// TODO: Perform header footer calculations
// . . .
NSUInteger startPage = 0;
for (id f in self.printFormatters) {
UIPrintFormatter *myFormatter = (UIPrintFormatter *)f;
// Top inset is only used if we want a different inset for the first page and we don't.
// The bottom inset is never used by a viewFormatter.
myFormatter.contentInsets = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
// Just to be sure, never allow the content to go past our minimum margins for the content area.
myFormatter.maximumContentWidth = self.paperRect.size.width - 2*MIN_MARGIN;
myFormatter.maximumContentHeight = self.paperRect.size.height - 2*MIN_MARGIN;
myFormatter.startPage = startPage;
startPage = myFormatter.startPage + myFormatter.pageCount;
}
// Let the superclass calculate the total number of pages
return [super numberOfPages];
}
I still don't know if there is anyway to APPEND the printable content of both htmlFormatter and listHtmlFormatter (using this approach). e.g. rather than using a new page for listHtmlFormatter, continue printing from where htmlFormatter ended.
I'm adding this extra info answer here because I spent 2 days dk'n around with this and Mustafa's answer saved me. Hopefully all this in one place will save others a lot of wasted time.
I was trying to figure out why I was unable get my custom UIPrintPageRenderer
to iterate over an array of viewPrintFormatter
from several UIWebViews
that I need to print in ONE job, and have it properly calculate pageCount as these Apple docs suggest it should: PrintWebView
The key was to add them via this method:
-(void)addPrintFormatter:(UIPrintFormatter *)formatter startingAtPageAtIndex:(NSInteger)pageIndex
and NOT this one:
@property(nonatomic, copy) NSArray <UIPrintFormatter *> *printFormatters
The Apple docs suggest that the UIPrintPageRenderer
gets page count from the print formatters in the array as long as the proper metrics are set on the print formatters, as Mustafa shows above. But it only works if you add them via addPrintFormatter:startingAtPageAtIndex:
If you add them as an array, the printFormatters (regardless of what metrics you set on them) will return a page count of 0!
One additional note for people using this approach, put the update to viewPrintFormatter.startPage
in a dispatch_async
block, else you'll get an exception:
dispatch_async(dispatch_get_main_queue(), ^{
myFormatter.startPage = startPage;
startPage = myFormatter.startPage + myFormatter.pageCount;
});
To add to @Mustafa's answer,
startPage needs to be declared as:
__block NSUInteger startPage
if it's to be used inside the dispatch_async block