文章目录
- 1.将整个view截图返回image:
- 2.截取view的部分区域,返回image:
- 3.旧方法:
- 4.Tips
- 参考:
1.将整个view截图返回image:
这些 api 已被废弃,所以需要判断 iOS 版本 写两套代码:
Replace usage of UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer.
Replace usage of UIGraphicsGetImageFromCurrentImageContext with UIGraphicsImageRendererContext.currentImage.
Swift 版本:
/// 截图整个view
/// - Returns: image
func mooSnapshot() -> UIImage? {
if self.window == nil {
return nil
}
let scale = UIScreen.main.scale
var image: UIImage? = nil
// 1. 创建绘图渲染格式
if #available(iOS 10.0, *) {
let format = UIGraphicsImageRendererFormat()
format.scale = scale
format.opaque = self.isOpaque
// 2. 创建绘图渲染器
let renderer = UIGraphicsImageRenderer(size: self.bounds.size,
format: format)
// 3. 绘制图
image = renderer.image { context in
let success = self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
print("draw success: \(success)")
}
} else {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, scale);
let success = self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
print("draw success: \(success)")
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return image
}
OC版本:
- (UIImage * _Nullable)mooSnapshot {
if (CGRectGetWidth(self.bounds) <= 0.0 || CGRectGetHeight(self.bounds) <= 0.0) {
return nil;
}
if (!self.window) {
return nil;
}
if (!self.superview) {
return nil;
}
CGFloat scale = [UIScreen mainScreen].scale;
UIImage *image = nil;
if (@available(iOS 10.0, *)) {
UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init];
format.scale = scale;
format.opaque = NO;
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:self.bounds.size
format:format];
image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
BOOL success = [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
NSLog(@"%p, Snapshot success: %@", self, @(success));
}];
} else {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, scale);
BOOL success = [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
NSLog(@"%p, Snapshot success: %@", self, @(success));
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return image;
}
2.截取view的部分区域,返回image:
Capture the frame area of the view.
Swift 版本:
import CoreGraphics
extension UIView {
/// 截取view的部分区域
/// - Parameter frame: 需要截取的区域
/// - Returns: image
func mooSnapshotForFrame(_ frame: CGRect) -> UIImage? {
guard let image = self.mooSnapshot() else { return nil }
guard let cgImage = image.cgImage else { return nil }
let scale = UIScreen.main.scale
// 根据屏幕倍率将 frame 进行缩放
let scaledRect = CGRectApplyAffineTransform(frame,
CGAffineTransformMakeScale(scale, scale))
// 根据 缩放frame 进行裁剪
guard let scaledCGImage = cgImage.cropping(to: scaledRect) else { return nil }
let returnImage = UIImage(cgImage: scaledCGImage)
return returnImage
}
}
OC 版本:
- (UIImage * _Nullable)mooSnapshotForFrame:(CGRect)frame {
if (CGRectGetWidth(frame) <= 0.0 || CGRectGetHeight(frame) <= 0.0) {
return nil;
}
UIImage *image = [self mooSnapshot];
if (!image) {
return nil;
}
CGFloat scale = [UIScreen mainScreen].scale;
CGRect scaledRect = CGRectApplyAffineTransform(frame, CGAffineTransformMakeScale(scale, scale));
CGImageRef cgImage = CGImageCreateWithImageInRect(image.CGImage, scaledRect);
UIImage *returnImage = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
return returnImage;
}
以下就是将一个view的上半部分截取成image后展示如下:
3.旧方法:
func mooSnapshot() -> UIImage? {
guard CGRectGetWidth(self.bounds) > 0.0 && CGRectGetHeight(self.bounds) > 0.0 else {
return nil
}
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0.0)
let success = self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
print("draw success: \(success)")
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndPDFContext()
return image
}
Replace usage of UIGraphicsBeginImageContext with UIGraphicsImageRenderer.
Replace usage of UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer.
Replace usage of UIGraphicsGetImageFromCurrentImageContext with UIGraphicsImageRendererContext.currentImage.
UIGraphicsEndImageContext should only be used alongside UIGraphicsBeginImageContext[WithOptions].
这些旧的 api 已经被废弃了,用文章开头的 api 代替
4.Tips
Tips1:得在加载到父视图 layout 后触发
Tips2:width 或 height 有一个为空 drawHierarchy 就会 crash(就版iOS不会crash,新版会)
参考:
drawViewHierarchyInRect:afterScreenUpdates:
ios drawViewHierarchyInRect crash EXC_BREAKPOINT UNKNOWN