I have simple UITableView
with some data. The table\'s height is greater than the screen size. Now I need to catch screenshot of this table (a whole table). I k
UItableView
by don't create all cells at a time, but you can force tableView to load all (which is not recommended) work around is just set the height of tableView
( numRows * heightOfRow)
and this will make it load tableView
all rows.
And you can convert view to image like below
+ (UIImage*)imageFromView:(UIView *)view{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, [UIScreen mainScreen].scale);
[view drawViewHierarchyInRect:CGRectMake(0, 0, view.bounds.size.width, view.bounds.size.height) afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
For snapshot in of uitableview with swift 2.2:
func printScreen(){
UIGraphicsBeginImageContextWithOptions(Table_LigaParcial.contentSize, false, UIScreen.mainScreen().scale)
Table_LigaParcial.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)
Table_LigaParcial.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let row = Table_LigaParcial.numberOfRowsInSection(0)
let numberofRowthatShowinscreen = 4
var scrollCount = row / numberofRowthatShowinscreen
for var i=0;i < scrollCount ; i+=1 {
Table_LigaParcial.scrollToRowAtIndexPath(NSIndexPath(forRow: (i)*numberofRowthatShowinscreen, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)
Table_LigaParcial.layer.renderInContext(UIGraphicsGetCurrentContext()!)
}
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
}
You can create graphics context with the size of tableView.contentSize. After that you have to run loop threw all indexPaths and draw each cell. You can have one cell which will be reused for drawing cells which are out of screen - just change content of that with required data and draw it.
Swift 4 version of Parth Bhadaja's answer:
func generateImage(tableView:UITableView) -> UIImage {
UIGraphicsBeginImageContext(tableView.contentSize);
tableView.scrollToRow(at: NSIndexPath(row: 0, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
tableView.layer.render(in: UIGraphicsGetCurrentContext()!)
let row = tableView.numberOfRows(inSection: 0)
let numberofRowthatShowinscreen = 4
let scrollCount = row / numberofRowthatShowinscreen
for i in 0..<scrollCount {
tableView.scrollToRow(at: NSIndexPath(row: (i+1)*numberofRowthatShowinscreen, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
tableView.layer.render(in: UIGraphicsGetCurrentContext()!)
}
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext();
return image;
}
Should be noted that this function does return an image of the whole tableView, even cells which haven't been loaded onto the screen yet.
add render
method to UITableView
through category
- (UIImage *)render {
//save the origin infos for later to restore
CGPoint originContentOffset = self.contentOffset;
//force jump to table view's top
self.contentOffset = CGPointZero;
UIGraphicsBeginImageContext(self.contentSize);
CGContextRef *ctx = UIGraphicsGetCurrentContext();
//render header
[self.tableHeaderView.layer renderInContext:ctx];
//render sections
NSInteger numberOfSections = [self numberOfSections];
for (int section = 0; section < numberOfSections; section++) {
NSInteger numberOfRows = [self numberOfRowsInSection:section];
for (int row = 0; row < numberOfRows; row++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
//check cell is visible
if ([self cellForRowAtIndexPath:indexPath]) {
[self scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:false];
[self.layer renderInContext:ctx];
}
}
}
//render footer
[self.tableFooterView.layer renderInContext:ctx];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//restore infos
self.contentOffset = originContentOffset;
return image;
}
Tranfered Parth Bhadaja's answer to Swift 3 and as extension with computed property:
extension UITableView {
var capturedImage : UIImage {
UIGraphicsBeginImageContext(contentSize);
scrollToRow(at: NSIndexPath(row: 0, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
layer.render(in: UIGraphicsGetCurrentContext()!)
let row = numberOfRows(inSection: 0)
let numberofRowthatShowinscreen = 4
let scrollCount = row / numberofRowthatShowinscreen
for i in 0 ..< scrollCount {
scrollToRow(at: NSIndexPath(row: (i+1)*numberofRowthatShowinscreen, section: 0) as IndexPath, at: UITableViewScrollPosition.top, animated: false)
layer.render(in: UIGraphicsGetCurrentContext()!)
}
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext();
return image;
}
}
Usage:
let image = tableView.capturedImage