UITableViewのキャプチャを簡単に撮る方法

# この記事について
UITableViewのキャプチャを簡単に撮る方法の紹介です。
というのも、MySplitTimeというアプリを作成する際、出来上がったスプリットをシェアするのに、画像化してシェアしようと考えたところ、いくつか方法を見つけたものの、スクロールする方法やダミーViewを作って画像化する方法。

もっとシンプルに出来るのでは、と思ったところ安定のStackOverflowにあったので、その紹介を。
https://stackoverflow.com/questions/37049770/capture-uitableview-as-image-with-scrolling

# UITableViewだけのキャプチャを撮る方法
```swift
/**
TableViewだけのキャプチャを作成
*/
func createViewImage() -> UIImage? {
	// キャプチャサイズにTableViewのcontentSizeを指定
	let captureSize = tableView.contentSize
	print("captureSize = \(captureSize)")
	
	// context生成
	UIGraphicsBeginImageContextWithOptions(captureSize, false, 0.0)
	
	// tableViewのframe退避
	let previousFrame = tableView.frame
	
	if let context = UIGraphicsGetCurrentContext(){
		// tableviewのframeを、コンテンツサイズに一時的に変更
		tableView.frame = CGRect(x:tableView.frame.origin.x,
								 y:tableView.frame.origin.y,
								 width:tableView.contentSize.width,
								 height:tableView.contentSize.height)
		// tableViewのレイヤを描画
		tableView.layer.render(in: context)
	}
	// tableViewのframe復帰
	tableView.frame = previousFrame
	
	// image生成
	let image = UIGraphicsGetImageFromCurrentImageContext()
	UIGraphicsEndImageContext();
	
	return image
}
```
ポイントは２つ
・キャプチャを撮るためにcontextのサイズは、tableViewのcontentSizeとする
・キャプチャ取得のときだけ、layer.renderの前にtableView.frameをコンテンツサイズに変更

# 全体キャプチャを撮る方法
viewcontroller.viewのキャプチャだけでは可視範囲だけになってしまいます。
全体を撮るために、contextのサイズをtableViewのcontentSize ＋ その他の領域とする必要があります。

```swift
/**
TableViewとImageViewのキャプチャを生成する
・TableViewより上の部分は、self.viewからのキャプチャとする
・そのキャプチャに被せるようにtableViewのキャプチャを載せる
*/
func createViewImage() -> UIImage? {
	// キャプチャサイズ計算
	let captureSize = CGSize(width: self.view.frame.size.width,
							 height: self.imageHolderView.frame.size.height + tableView.contentSize.height)
	print("captureSize = \(captureSize)")
	
	// context生成
	UIGraphicsBeginImageContextWithOptions(captureSize, false, 0.0)
	
	// tableViewのframe退避
	let previousFrame = tableView.frame
	
	// UINavigationController調整
	var topAdjust: CGFloat = 0
	if let _ = self.navigationController {
		// 最上部に描画するViewからy座標の位置分調整する
		// もしくは、NavigationControllerの高さとステータスバーの高さを調整としても良い
		topAdjust = self.imageHolderView.frame.origin.y
	}
	if let context = UIGraphicsGetCurrentContext(){
		
		// NavigationControllerが描画域に入らないように調整して描画
		context.translateBy(x: 0, y: -topAdjust)
		self.view.layer.render(in: context)
		context.translateBy(x: 0, y: topAdjust)
		
		// tableViewの描画にむけ、contextをimageView分だけ移動
		context.translateBy(x: 0, y: self.imageHolderView.frame.size.height)
		// tableviewのframeを、コンテンツサイズに一時的に変更
		tableView.frame = CGRect(x:tableView.frame.origin.x,
								 y:tableView.frame.origin.y,
								 width:tableView.contentSize.width,
								 height:tableView.contentSize.height)
		// tableViewのレイヤを描画
		tableView.layer.render(in: context)
	}
	// tableViewのframe復帰
	tableView.frame = previousFrame
	
	// image生成
	let image = UIGraphicsGetImageFromCurrentImageContext()
	UIGraphicsEndImageContext();
	
	return image
}
```

上記はviewcontroller.viewとtableViewのキャプチャを繋げるようにしています。
viewcontroller.viewのframeを、描画域外のcontentSize.height分足して上げるほうがよりシンプルかもしれません。
（UINavigationControllerがある場合は、self.view.layer.renderにその分の上部余白が生まれることを考慮する必要があります）

# サンプル
githubにサンプルコードを載せてます
https://github.com/dchssk/TableViewCapture

これを実際に使って公開しているアプリです
https://itunes.apple.com/jp/app/mysplittime/id1437885505?mt=8

# 参考
https://stackoverflow.com/questions/37049770/capture-uitableview-as-image-with-scrolling