iOS 防截图需求(伪)实现

作者: 山已几孑 | 来源:发表于2019-12-23 11:15 被阅读0次

    需求: 防截图,安卓可以通过系统级的禁止截图来实现,但是iOS并不允许开发者这么做,另外,这个功能本身就是一个鸡肋,别人完全可以通过用别的手机拍照的形式获取屏幕信息,更多是一种警告意味,本文实现的防截图功能,依赖于Photos框架的performChanges方法,实现了 当用户截图时,提示用户删除,且必须删除,可以多张图片进行监听并删除

    • 首先是权限问题,该功能需要相册使用权限,且必须提前进行申请,否则,第一张图片无法获取并删除。
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            switch (status) {
                case PHAuthorizationStatusNotDetermined:
                    // User has not yet made a choice with regards to this application
                    break;
                case PHAuthorizationStatusRestricted:// This application is not authorized to access photo data.
                    // The user cannot change this application’s status, possibly due to active restrictions
                    //   such as parental controls being in place.
                case PHAuthorizationStatusDenied:           // User has explicitly denied this application access to photos data.
                {
                    UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"权限异常" message:@"使用此APP需要相册使用权限,请前往设置-移动C3开启权限" preferredStyle:UIAlertControllerStyleAlert];
                    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
                        abort(); //强制退出
                    }]];
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:true completion:nil];
                    });
                    
                }
                    break;
                case PHAuthorizationStatusAuthorized:
                    break;
                default:
                    break;
            }
        }];
    
    • 初始化了一些属性来配合整个业务流转的顺序的控制
    @property(nonatomic, strong)NSOperationQueue * snapshotQueue;
    @property(nonatomic, assign)NSInteger snapshotCount;
    @property(nonatomic, retain)dispatch_semaphore_t semaphore;
    
        self.snapshotCount = 0;    
    //当做串行的queue使用
        self.snapshotQueue = [[NSOperationQueue alloc]init];
        self.snapshotQueue.maxConcurrentOperationCount = 1;
        self.semaphore = dispatch_semaphore_create(0);
    
    • 对系统的截屏时间进行监听,这里没啥好说的
            [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(receiveScreenShotNotification:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
    
    
    • 收到截屏事件后,维护一个本地的统计数字
    - (void)receiveScreenShotNotification:(NSNotification *)notify {
        self.snapshotCount++;
    }
    
    • 统计数字改变后,根据统计数字状态,来决定是否需要激活删除的事件
    - (void)setSnapshotCount:(NSInteger)snapshotCount {
        BOOL needDelete = _snapshotCount < snapshotCount;
        _snapshotCount = snapshotCount;
        
        NSLog(@"setSnapshotCount changed: %ld",needDelete);
        if (needDelete) {
            [self deleteCounted];
        }
    }
    
    • 激活删除图片, 这里,贴了两个方法,是因为,系统拍照需要处理事时间,当我们收到拍照事件时,系统相册可能还没有处理完成,此时获取到的最后一张图片是错误的,因此,我们需要尽可能的延迟代码调用顺序,这里通过弹窗来做延迟,也可以直接写延迟执行,但是时间不是很稳定,测试发现300毫秒可以稍微稳定一点,1s更好,但是流程上面就有了延迟。
    -(void)deleteCounted {
        
        [self.snapshotQueue cancelAllOperations];
    
        [self.snapshotQueue addOperationWithBlock:^{
            if (self.snapshotCount == 0) { //如果count==0,那么不用再删除了
                return ;
            }
            dispatch_async(dispatch_get_main_queue(), ^{
    
                UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"警告" message:@"我们的APP禁止截屏,请自觉删除!" preferredStyle:UIAlertControllerStyleAlert];
                
                [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                    [self deleteAssets];
                }]];
                [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:true completion:^{
                    
                }];
            });
            dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
        }];
        
    }
    
    -(void)deleteAssets {
    
        PHFetchOptions *options = [[PHFetchOptions alloc] init];
        options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
        
        PHFetchResult *assetsFetchResults = [PHAsset fetchAssetsWithOptions:options];
        
        NSMutableArray <PHAsset *>* assets = [NSMutableArray arrayWithCapacity:self.snapshotCount];
        if (self.snapshotCount >= 0) {
            for (int i = 0; i < self.snapshotCount; i ++) {
                PHAsset *asset = [assetsFetchResults objectAtIndex:i];
                [assets addObject:asset];
            }
        }
        __weak typeof(self) weakSelf = self;
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            
            [PHAssetChangeRequest deleteAssets:assets];
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            if (!success) {
                
                [weakSelf deleteNewAssets:assets];
            } else {
                self.snapshotCount -= assets.count;
                dispatch_semaphore_signal(self.semaphore);
            }
        }];
    }
    
    • 因为删除事件是系统功能,因此存在用户手动取消的情况,这里采用在取消时,继续弹出删除来解决
    - (void)deleteNewAssets:(NSArray<PHAsset *> *)assets {
        
        if (assets) {//增加一层判断,安全第一
            __weak typeof(self) weakSelf = self;
            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                
                [PHAssetChangeRequest deleteAssets:assets];
            } completionHandler:^(BOOL success, NSError * _Nullable error) {
                if (!success) {
                    [weakSelf deleteNewAssets:assets];
                } else {
                    self.snapshotCount -= assets.count;
                    dispatch_semaphore_signal(self.semaphore);
                }
            }];
        }
    }
    

    相关文章

      网友评论

        本文标题:iOS 防截图需求(伪)实现

        本文链接:https://www.haomeiwen.com/subject/igomnctx.html