截屏有两种方案 根据自己需求选择
1 获取系统截图 截图后 监听相册发生变化通知 获取相册第一张图片展示 。优点 截图的内容不会出错 缺点需要获取读取相册的权限
2 自己截图 收到系统截图通知后 自己截图 。优点是不需要权限 缺点是针对在webView上播放的视频 截取不到 只能截取到webView的背景色 因为着急上线没有细跟
第一种方案
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface RMScreenshotsService : NSObject
/// 截图展示的视图
@property(nonatomic,strong,nullable) UIView *screenshotsView;
/// 图片处理完成
/// @param image 截屏得到的图片
@property(nonatomic, copy) void (^ imageSettingCompletedBlock)(UIImage *image);
/// 单例
+ (RMScreenshotsService *)shareInstance;
@end
#import "RMScreenshotsService.h"
#import "UIImage+RMCompress.h"
#import "RMHelper.h"
#import <Photos/Photos.h>
@interface RMScreenshotsService()<PHPhotoLibraryChangeObserver>
/// 用于比对图片是否是同一张
@property (nonatomic,strong) NSString *localIdentifier;
/// 是否收到截屏通知
@property (nonatomic,assign) BOOL *isDidTakeScreenshot;
@end
@implementation RMScreenshotsService
- (instancetype)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidTakeScreenshot:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
[PHPhotoLibrary.sharedPhotoLibrary registerChangeObserver:self];
}
return self;
}
/// 单例
+ (RMScreenshotsService *)shareInstance {
static RMScreenshotsService *service = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
service = [[RMScreenshotsService alloc] init];
});
return service;
}
- (void)photoLibraryDidChange:(PHChange *)changeInstance{
if (!self.isDidTakeScreenshot) {
return;
}
self.isDidTakeScreenshot = false;
PHAsset *phasset = [[self class] latestAsset];
if ([phasset.localIdentifier isEqualToString:self.localIdentifier] ) {
return;
}
self.localIdentifier = phasset.localIdentifier;
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status){
if (status == PHAuthorizationStatusAuthorized)
{
[self fetchImageWithAsset:phasset imageBlock:^(NSData *data) {
UIImage *image = [UIImage imageWithData:data];
if (self.imageSettingCompletedBlock) {
self.imageSettingCompletedBlock(image);
}
}];
}
}];
}
- (void)userDidTakeScreenshot:(NSNotification *)notification
{
NSLog(@"检测到截屏");
self.screenshotsView.hidden = true;
self.isDidTakeScreenshot = true;
}
/**
通过资源获取图片的数据
@param mAsset 资源文件
@param imageBlock 图片数据回传
*/
- (void)fetchImageWithAsset:(PHAsset*)mAsset imageBlock:(void(^)(NSData *))imageBlock {
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.synchronous = YES;
options.networkAccessAllowed = YES;
options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
[[PHImageManager defaultManager] requestImageDataForAsset:mAsset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
// 直接得到最终的 NSData 数据
if (imageBlock) {
imageBlock(imageData);
}
}];
}
+ (PHAsset *)latestAsset
{
// 获取所有资源的集合,并按资源的创建时间排序
PHFetchOptions *options = [[PHFetchOptions alloc] init];
options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
PHFetchResult *assetsFetchResults = [PHAsset fetchAssetsWithOptions:options];
return [assetsFetchResults firstObject];
}
第二种方案:
在 userDidTakeScreenshot 中调用该方法
/// 截屏
- (NSData *)dataWithScreenshotInPNGFormat
{
CGSize imageSize = CGSizeZero;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsPortrait(orientation))
imageSize = [UIScreen mainScreen].bounds.size;
else
imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
CGContextSaveGState(context);
CGContextTranslateCTM(context, window.center.x, window.center.y);
CGContextConcatCTM(context, window.transform);
CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
if (orientation == UIInterfaceOrientationLandscapeLeft)
{
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, 0, -imageSize.width);
}
else if (orientation == UIInterfaceOrientationLandscapeRight)
{
CGContextRotateCTM(context, -M_PI_2);
CGContextTranslateCTM(context, -imageSize.height, 0);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
}
if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
{
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
}
else
{
[window.layer renderInContext:context];
}
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return UIImageJPEGRepresentation(image, 1);
}
@end