1

I need my app to render everything that a view controller has the potential to display (including off-screen content) except for the top and bottom navigation bars.

The first image, below, shows the view controller at runtime. The action menu triggers the following code which is adapted the code sample from the answer given here :

@IBAction func actionMenu(_ sender: Any) {

    let activityItems = [generateImageOfTableView(tblview: tourneyEntrants)]
    let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

    activityController.popoverPresentationController?.sourceView = self.view
    activityController.popoverPresentationController?.sourceRect = self.view.frame

    self.present(activityController, animated: true, completion: nil)
}

func generateImageOfTableView(tblview: UITableView) -> UIImage {

    var image = UIImage()

    UIGraphicsBeginImageContextWithOptions(tblview.contentSize, false, UIScreen.main.scale)

    // save initial values
    let savedContentOffset = tblview.contentOffset;
    let savedFrame = tblview.frame;
    let savedBackgroundColor = tblview.backgroundColor

    // reset offset to top left point
    tblview.contentOffset = CGPoint(x: 0, y: 0);
    // set frame to content size
    tblview.frame = CGRect(x: 0, y: 0, width: tblview.contentSize.width, height: tblview.contentSize.height);
    // remove background
    tblview.backgroundColor = UIColor.clear

    // make temp view with scroll view content size
    // a workaround for issue when image on ipad was drawn incorrectly
    let tempView = UIView(frame: CGRect(x: 0, y: 0, width: tblview.contentSize.width, height: tblview.contentSize.height))

    // save superview
    let tempSuperView = tblview.superview
    // remove scrollView from old superview
    tblview.removeFromSuperview()
    // and add to tempView
    tempView.addSubview(tblview)

    // render view
    // drawViewHierarchyInRect not working correctly
    tempView.layer.render(in: UIGraphicsGetCurrentContext()!)
    // and get image
    image = UIGraphicsGetImageFromCurrentImageContext()!

    // and return everything back
    tempView.subviews[0].removeFromSuperview()
    tempSuperView?.addSubview(tblview)

    // restore saved settings
    tblview.contentOffset = savedContentOffset;
    tblview.frame = savedFrame;
    tblview.backgroundColor = savedBackgroundColor

    UIGraphicsEndImageContext()

    return image
}

The second image, below, shows the image captured from this code.

There are two problems with it.

The first is that it is ignoring the text field and label above the table. I know that the code doesn't look for this, so I am looking for some guidance on how to capture the superview's contents (minus the navigation bars).

Second, the table view contains 18 columns of numbers but these aren't captured. So, the code copes with the height of the table being beyond the screen but not with the width. I've looked at whether auto layout maybe causing this, but cannot see anything obvious.

Rendered capture from screen View controller at run-time

Dave
  • 71
  • 10
  • 1
    I think you'll always have an issue with capturing the *full* contents of a `UITableView` if you intend to capture cells that are not part of the display. It's the nature of that - queueing/dequeing cells - that will be a problem. Even if it's embedded in something where 5 cells are visible and it contains 8 cells but there is 18 cells in it's datasource... you'll *at best* get 8 cells captured. –  Jan 08 '18 at 00:15
  • @dfd, the code I have included is able to show *all* rows in the `UITableView`, even those not part of the display just fine. The issue is the columns. I feel it may have something to do with the way I've laid out the storyboard. – Dave Jan 08 '18 at 17:14

0 Answers0