I have a UITableView
which is populated with some data but since it contains data that is more cells than the viewable area of the screen, I only managed to get onl
I think everyone forgets that UITableView
is a UIScrollView
after all. There is no need to calculate cells, height etc. You can simply create your context with the contentSize
, set tableView.frame.size = tableView.contentSize
and render in context.
Please see this example
UIGraphicsBeginImageContext(tableView.contentSize)
let context = UIGraphicsGetCurrentContext()
let cachedOffset = CGPoint(x:tableView.contentOffset.x , y:tableView.contentOffset.y)
let cachedFrame = tableView.frame
tableView.contentOffset = .zero
tableView.frame = CGRect(x: 0, y: 0, width: tableView.contentSize.width, height: tableView.contentSize.height)
tableView.layer.render(in: context)
tableView.frame = cachedFrame
tableView.contentOffset = cachedOffset
if let image = UIGraphicsGetImageFromCurrentImageContext() {
let imageView = UIImageView(image: image)
self.createPDF(fromUIViews:myImage saveToDocumentsWithFileName:"PDF Name")
}
UIGraphicsEndImageContext()
Based on Vin's answer (also can be used for snapshotting UIScrollViews):
UIGraphicsBeginPDFContextToData(pdfData, CGRectMakeWithSize(0, 0, self.productsTable.contentSize), nil);
UIGraphicsBeginPDFPage();
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
[self.productsTable scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[self.productsTable.layer renderInContext:UIGraphicsGetCurrentContext()];
CGFloat screensInTable = self.productsTable.contentSize.height / self.productsTable.height;
for (int i = 1; i < screensInTable; i++) {
CGPoint contentOffset = CGPointMake(0, i * self.productsTable.height);
[self.productsTable setContentOffset:contentOffset animated:NO];
[self.productsTable.layer renderInContext:UIGraphicsGetCurrentContext()];
}
UIGraphicsEndPDFContext();
Here's how you can do it without scrolling the tableview. Simply increase the height of the scrollview to the contentSize. The quality of the PDF is also better if you don't go via a UIImage
. This is from my UITableView
extension in Swift. The code is stolen from here and there so the comments aren't always mine.
func toPDF(fileName: String) -> String {
// Don't include scroll indicators in file
self.showsVerticalScrollIndicator = false
// Creates a mutable data object for updating with binary data, like a byte array
let pdfData = NSMutableData()
// Change the frame size to include all data
let originalFrame = self.frame
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.contentSize.width, self.contentSize.height)
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, self.bounds, nil)
UIGraphicsBeginPDFPage()
let pdfContext = UIGraphicsGetCurrentContext();
// Draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
self.layer.renderInContext(pdfContext!)
// Remove PDF rendering context
UIGraphicsEndPDFContext()
// Retrieves the document directories from the iOS device
let documentDirectories: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentDirectory = documentDirectories.objectAtIndex(0)
let documentDirectoryFilename = documentDirectory.stringByAppendingPathComponent(fileName);
// Instructs the mutable data object to write its context to a file on disk
pdfData.writeToFile(documentDirectoryFilename, atomically: true)
// Back to normal size
self.frame = originalFrame
// Put back the scroll indicator
self.showsVerticalScrollIndicator = true
return documentDirectoryFilename
}
UIGraphicsBeginImageContext(self.myTableView.contentSize);
[self.myTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
[self.myTableView.layer renderInContext:UIGraphicsGetCurrentContext()];
int rows = [self.myTableView numberOfRowsInSection:0];
int numberofRowsInView = 4;
for (int i =0; i < rows/numberofRowsInView; i++) {
[self.myTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(i+1)*numberofRowsInView inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
[self.myTableView.layer renderInContext:UIGraphicsGetCurrentContext()];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIImageView *myImage=[[UIImageView alloc]initWithImage:image];
UIGraphicsEndImageContext();
[self createPDFfromUIViews:myImage saveToDocumentsWithFileName:@"PDF Name"];
i dont know but this code works like a charm for me..
There are no offscreen cells because they are recycled as soon as they scroll out of the visible screen. Instead screenshoting the UITableView, you should consider creating a PDF version using Core Text. Maybe you can adapt this example.