How to get a snapshot of UITableView in a PDF format

纵然是瞬间 提交于 2019-11-29 22:41:29
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..

pierrovic

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
}

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.

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();

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()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!