0

Thanks to gleb vodovozov's idea , I can capture the image of entire my TableView including offscreen parts but the superview doesn't restore my TableView as its "before changes" position after using it to render image in a tempView.

I've checked his code carefully and I didn't see any issues. Maybe just because of iOS 13 "changes" so the code that works with previous iOS versions is malfunctioning now?

Below is his code

Any help is strongly appreciated!

var image = UIImage()
    UIGraphicsBeginImageContextWithOptions(self.myTable.contentSize, false, UIScreen.main.scale)

    // save initial values
    let savedContentOffset = self.myTable.contentOffset
    let savedFrame = self.myTable.frame
    let savedBackgroundColor = self.myTable.backgroundColor

    // reset offset to top left point
    self.myTable.contentOffset = CGPoint(x: 0, y: 0)
    // set frame to content size
    self.myTable.frame = CGRect(x: 0, y: 0, width: self.myTable.contentSize.width, height: self.myTable.contentSize.height)
    // remove background
    self.myTable.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: self.myTable.contentSize.width, height: self.myTable.contentSize.height))

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

    // 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(self.myTable)

    // restore saved settings
    self.myTable.contentOffset = savedContentOffset
    self.myTable.frame = savedFrame
    self.myTable.backgroundColor = savedBackgroundColor

    UIGraphicsEndImageContext()

    return image
NguyenTon
  • 1
  • 2

2 Answers2

1
// remove scrollView from old superview
self.myTable.removeFromSuperview()

From documentation:

func removeFromSuperview(): Calling this method removes any constraints that refer to the view you are removing, or that refer to any view in the subtree of the view you are removing.

I know that you restore the frame, but you may need to save constraints in array before removing it from super view, then add them again after adding it again to super view.

// Save constraints
guard let superView = myTable.superView else {
   return
}
var oldConstraints: [NSLayoutConstraint] = []
for constraint in superView.constraints {
   if constraint.firstItem == myTable || constraint.secondItem == myTable {
       oldConstraints.append(constraint)
   }
}

self.myTable.removeFromSuperview()

// ...

tempSuperView?.addSubview(self.myTable)

// Restore old constraints
NSLayoutConstraint.activate(oldConstraints)
Ahmed Osama
  • 854
  • 1
  • 8
  • 17
0

I've added tableview's old constraints to this function.

func screenshot() -> UIImage{        
        var image = UIImage();
        UIGraphicsBeginImageContextWithOptions(self.tableView.contentSize, false, UIScreen.main.scale)
        
        // save initial values
        let savedContentOffset = self.tableView.contentOffset;
        let savedFrame = self.tableView.frame;
        let savedBackgroundColor = self.tableView.backgroundColor
        
        // reset offset to top left point
        self.tableView.contentOffset = CGPoint(x: 0, y: 0);
        // set frame to content size
        self.tableView.frame = CGRect(x: 0, y: 0, width: self.tableView.contentSize.width, height: self.tableView.contentSize.height);
        // remove background
        self.tableView.backgroundColor = self.tableView.backgroundColor;
        
        // 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: self.tableView.contentSize.width, height: self.tableView.contentSize.height));
        
     
        
        // save superview
        let tempSuperView = self.tableView.superview
        
        // Save constraints
        guard let superView = self.tableView.superview else {
            return UIImage();
        }
        
        //get old constraints from table
        var oldConstraints: [NSLayoutConstraint] = []
        for constraint in superView.constraints {
            if constraint.firstItem as? NSObject == self.tableView || constraint.secondItem as? NSObject == self.tableView{
               oldConstraints.append(constraint)
           }
        }
        
        // remove scrollView from old superview
        self.tableView.removeFromSuperview()
        // and add to tempView
        tempView.addSubview(self.tableView)
        
        // 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(self.tableView)
        
        //activate table's old constraints
        NSLayoutConstraint.activate(oldConstraints)
        
        // restore saved settings
        self.tableView.contentOffset = savedContentOffset;
        self.tableView.frame = savedFrame;
        self.tableView.backgroundColor = savedBackgroundColor
         
        UIGraphicsEndImageContext();
        
        
        return image
    }