How to convert a UIView to an image
An extension on UIView
should do the trick.
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
Apple discourages using UIGraphicsBeginImageContext
starting iOS 10 with the introduction of the P3 color gamut. UIGraphicsBeginImageContext
is sRGB and 32-bit only. They introduced the new UIGraphicsImageRenderer
API that is fully color managed, block-based, has subclasses for PDFs and images, and automatically manages the context lifetime. Check out WWDC16 session 205 for more details (image rendering begins around the 11:50 mark)
To be sure that it works on every device, use #available
with a fallback to earlier versions of iOS:
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
} else {
UIGraphicsBeginImageContext(self.frame.size)
self.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return UIImage(cgImage: image!.cgImage!)
}
}
}
How to capture UIView to UIImage without loss of quality on retina display
Switch from use of UIGraphicsBeginImageContext
to UIGraphicsBeginImageContextWithOptions
(as documented on this page). Pass 0.0 for scale (the third argument) and you'll get a context with a scale factor equal to that of the screen.
UIGraphicsBeginImageContext
uses a fixed scale factor of 1.0, so you're actually getting exactly the same image on an iPhone 4 as on the other iPhones. I'll bet either the iPhone 4 is applying a filter when you implicitly scale it up or just your brain is picking up on it being less sharp than everything around it.
So, I guess:
#import <QuartzCore/QuartzCore.h>
+ (UIImage *)imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
And in Swift 4:
func image(with view: UIView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
view.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
return nil
}
How Do I Take a Screen Shot of a UIView?
I think you may want renderInContext
, not drawInContext
. drawInContext is more a method you would override...
Note that it may not work in all views, specifically a year or so ago when I tried to use this with the live camera view it did not work.
How to convert UIView to UIImage with high resolution?
You need to set the correct content scale on each subview.
extension UIView {
func scale(by scale: CGFloat) {
self.contentScaleFactor = scale
for subview in self.subviews {
subview.scale(by: scale)
}
}
func getImage(scale: CGFloat? = nil) -> UIImage {
let newScale = scale ?? UIScreen.main.scale
self.scale(by: newScale)
let format = UIGraphicsImageRendererFormat()
format.scale = newScale
let renderer = UIGraphicsImageRenderer(size: self.bounds.size, format: format)
let image = renderer.image { rendererContext in
self.layer.render(in: rendererContext.cgContext)
}
return image
}
}
To create your image:
let image = yourView.getImage()
Related Topics
Difference Between Static Function and Singleton Class in Swift
Autolayout, Unable to Simultaneously Satisfy Constraints
Creating a Percentage Based iOS Layout
How to Use the Uisearchbar and Uisearchdisplaycontroller
iOS Nsattributedstring on Uibutton
Exc_Bad_Instruction (Code=Exc_I386_Invop, Subcode=0X0) on Dispatch_Semaphore_Dispose
Styling the Cancel Button in a Uisearchbar
Fatal Error: Init(Coder:) Has Not Been Implemented Error Despite Being Implemented
Open Uisplitviewcontroller to Master View Rather Than Detail
Ios: Add Imageview in a Scrollview to Have Zoom
How Shouldchangecharactersinrange Works in Swift
Custom Uifont Baseline Shifted
Uiview's Border Color in Interface Builder Doesn't Work
Detect If the Application in Background or Foreground in Swift
Transition Animation Not Working in Swiftui
Rotate Uiview Around Its Center Keeping Its Size
Uikeyboardboundsuserinfokey Is Deprecated, What to Use Instead