How to get a snapshot of UITableView in a PDF format

前端 未结 5 474
一向
一向 2021-01-31 12:22

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

相关标签:
5条回答
  • 2021-01-31 13:09

    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()
    
    0 讨论(0)
  • 2021-01-31 13:10

    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();
    
    0 讨论(0)
  • 2021-01-31 13:12

    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
    }
    
    0 讨论(0)
  • 2021-01-31 13:18
    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..

    0 讨论(0)
  • 2021-01-31 13:19

    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.

    0 讨论(0)
提交回复
热议问题