iOSのUIをそのまま画像にする方法です。AVCaptureOutputで撮った写真と何かのViewを合成した画像を出したいみたいなときに使えます。

以下のコードでUIImageに変換ができます。ここでのViewは色々なSubviewなんかが入っている、画像として取り出したいViewです。

func convertToUIImage(_ view: UIView) -> UIImage {
    UIGraphicsBeginImageContext(view.bounds.size)
    //UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0)
    let context = UIGraphicsGetCurrentContext()!
    view.layer.render(in: context)
    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}

ところが、これだと画面上のサイズそのままで出力されてしまいます。Retinaディスプレイなど解像度が高いディスプレイではその倍の情報があるにも関わらず半分になってしまいます。例えば画面上で300x300のViewであれば600x600の画像にできるはずなのですが、↑の書き方だと300x300になってしまう。

これだと勿体ないので少し変更します。UIGraphicsBeginImageContextするところを、UIGraphicsBeginImageContextWithOptionsを使ってスケールの指定をします。

// Before
// UIGraphicsBeginImageContext(view.bounds.size)

// After
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0)

3番目の引数の0がスケールで、ここをゼロにすると端末のスクリーンに応じてスケールを変えてくれるそうです。

If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.