自由的羽毛 发表于 2024-8-5 09:36:42

iOS_给View的部门区域截图 snapshot for view

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 = false
      // 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, false, 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 = .scale;
    UIImage *image = nil;
    if (@available(iOS 10.0, *)) {
      UIGraphicsImageRendererFormat *format = [ init];
      format.scale = scale;
      format.opaque = NO;
      UIGraphicsImageRenderer *renderer = [ initWithSize:self.bounds.size
                                                                                 format:format];
      image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
            BOOL success = ;
            NSLog(@"%p, Snapshot success: %@", self, @(success));
      }];
    } else {
      UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, scale);
      BOOL success = ;
      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 = ;
    if (!image) {
      return nil;
    }
    CGFloat scale = .scale;
    CGRect scaledRect = CGRectApplyAffineTransform(frame, CGAffineTransformMakeScale(scale, scale));
    CGImageRef cgImage = CGImageCreateWithImageInRect(image.CGImage, scaledRect);
    UIImage *returnImage = ;
    CGImageRelease(cgImage);
    return returnImage;
}
以下就是将一个view的上半部门截取成image后展示如下:
https://i-blog.csdnimg.cn/blog_migrate/9a226a6e8381a028892556b27965de08.png
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.
这些旧的 api 已经被废弃了,用文章开头的 api 取代
4.Tips

   Tips1:得在加载到父视图 layout 后触发
Tips2:width 或 height 有一个为空 drawHierarchy 就会 crash(就版iOS不会crash,新版会)
参考:

drawViewHierarchyInRect:afterScreenUpdates:
ios drawViewHierarchyInRect crash EXC_BREAKPOINT UNKNOWN

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: iOS_给View的部门区域截图 snapshot for view