I assume you're talking about printing using the iOS printing system, described in the “Printing” chapter of the Drawing and Printing Guide for iOS.
Since -[UITableView viewPrintFormatter]
doesn't return a usable UIViewPrintFormatter
, you have to find another way to do it. Let's write a function that turns a table view into a PDF:
static NSData *pdfDataWithTableView(UITableView *tableView) {
First, we'll save away the view's current bounds, so we can restore the bounds at the end.
CGRect priorBounds = tableView.bounds;
Now we'll ask the table view to figure out how tall it needs to be to fit all of its rows.
CGSize fittedSize = [tableView sizeThatFits:CGSizeMake(priorBounds.size.width, HUGE_VALF)];
And we'll go ahead and resize the table view to be that big. We also set its origin (which is the same as its contentOffset
) to 0,0 so it will actually contain all of its rows.
tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);
We'll need a CGRect
containing the bounds of our PDF page.
// Standard US Letter dimensions 8.5" x 11"
CGRect pdfPageBounds = CGRectMake(0, 0, 612, 792);
Now we can create a PDF graphics context.
NSMutableData *pdfData = [[NSMutableData alloc] init];
UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds, nil); {
We need to render the table view into the graphics context. Since the table view may be taller than the page size, we step the origin of the context down the Y axis in increments of the page height.
for (CGFloat pageOriginY = 0; pageOriginY < fittedSize.height; pageOriginY += pdfPageBounds.size.height) {
We tell the context to begin a page.
UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);
Since we're going to change the context's origin, we will save the graphics state and restore it after rendering this page.
CGContextSaveGState(UIGraphicsGetCurrentContext()); {
Now we can adjust the origin of the context so that the top-left corner of the rendering area is at the appropriate point in our table view's coordinate system.
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -pageOriginY);
Finally we can tell the table view's layer to render itself to the context. Everything outside of the current page's bounds will be clipped away.
[tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
To clean up, we restore the graphics state.
} CGContextRestoreGState(UIGraphicsGetCurrentContext());
At this point, if there are more pages, we'll go back to the top of the for
loop.
}
Now we've rendered all of the pages, so we can end the PDF graphics context.
} UIGraphicsEndPDFContext();
And we need to restore the table view's bounds.
tableView.bounds = priorBounds;
And finally we can return the PDF data.
return pdfData;
}
Here it is all together:
static NSData *pdfDataWithTableView(UITableView *tableView) {
CGRect priorBounds = tableView.bounds;
CGSize fittedSize = [tableView sizeThatFits:CGSizeMake(priorBounds.size.width, HUGE_VALF)];
tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);
// Standard US Letter dimensions 8.5" x 11"
CGRect pdfPageBounds = CGRectMake(0, 0, 612, 792);
NSMutableData *pdfData = [[NSMutableData alloc] init];
UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds, nil); {
for (CGFloat pageOriginY = 0; pageOriginY < fittedSize.height; pageOriginY += pdfPageBounds.size.height) {
UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);
CGContextSaveGState(UIGraphicsGetCurrentContext()); {
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -pageOriginY);
[tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
} CGContextRestoreGState(UIGraphicsGetCurrentContext());
}
} UIGraphicsEndPDFContext();
tableView.bounds = priorBounds;
return pdfData;
}
You could of course use UIGraphicsBeginPDFContextToFile
instead. That would use a lot less working memory.
Either way, once you have the PDF (in memory or in a file), you can use the iOS printing system to send it to a printer.