I want to generate a .png
file from UIView snapshot but it's always nil
. Could you give me a hint what's wrong with my code? I'm running Catalina 10.15.2 with Xcode 11.3 and iOS 13.3.
Here's my code's snippet:
extension UIView {
fileprivate func snapShot(view: UIView) -> UIView {
let snapshot = view.snapshotView(afterScreenUpdates: false)
self.addSubview(snapshot!)
return snapshot!
}
}
class ViewController: UIViewController {
var image: UIImage?
var imageView: UIImageView?
@IBAction func take(_ sender: UIButton) {
let oneThird = CGRect(x: 0,
y: 0,
width: view.frame.size.width / 3,
height: view.frame.size.height / 3)
let snap = view.snapShot(view: self.view)
snap.frame = oneThird
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
let png = snap.largeContentImage?.pngData()
if let pngData = png {
self.image = UIImage(data: pngData)
}
self.imageView = UIImageView(image: self.image)
}
print(self.view.subviews.indices) // 0..<5
print(imageView?.image as Any) // NIL
}
}
Any help appreciated.
Try the following extension:
extension UIView {
func getImageFromCurrentContext(bounds: CGRect? = nil) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds?.size ?? self.bounds.size, false, 0.0)
self.drawHierarchy(in: bounds ?? self.bounds, afterScreenUpdates: true)
guard let currentImage = UIGraphicsGetImageFromCurrentImageContext() else {
return nil
}
UIGraphicsEndImageContext()
return currentImage
}
}
Pass the bounds if you would like 1/3 of the view or don't provide a bounds to get the image of the entire view.
Tested with sample code:
import UIKit
class ViewController: UIViewController {
@IBOutlet private(set) var testView: UIView!
@IBOutlet private(set) var testImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.testImageView.image = self.testView.getImageFromCurrentContext()
}
}
}
I made UIView
on the storyboard have a sample label inside it and changed the background color just to verify it is in fact creating the image. Then added an UIImageView
under that. Connected the UIView
to testView
and the UIImageView
to testImageView
.