iOS如何检测截图并屏蔽内容(仿WhatsApp View Once图片)
实现WhatsApp View Once截图遮罩的可行方案
iOS没有公开API能在截图动作发生前触发通知,WhatsApp的实现核心是利用系统截图的快照特性+多信号组合响应,让遮罩被截图捕获,同时优化用户体验,具体思路如下:
核心思路拆解
系统截图会直接捕获当前屏幕的UI层级,因此只要遮罩在截图快照生成时处于显示状态,最终的截图就会包含遮罩。结合现有公开API,可通过以下方式实现:
1. 利用屏幕捕获状态通知覆盖录屏+部分截图场景
UIScreen.capturedDidChangeNotification主要用于监听录屏、屏幕镜像等持续捕获场景,但部分iOS版本中,截图动作会短暂触发isCaptured状态切换。通过监听这个通知,我们可以提前显示遮罩:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(handleCaptureStateChange), name: UIScreen.capturedDidChangeNotification, object: nil ) } @objc private func handleCaptureStateChange(_ notification: Notification) { guard let screen = notification.object as? UIScreen else { return } screen.isCaptured ? showMask() : hideMask() } private func showMask() { // 假设maskView是提前添加在内容上方的遮罩层 maskView.alpha = 1.0 } private func hideMask() { maskView.alpha = 0.0 }
2. 事后补救:处理截图完成后的场景
对于capturedDidChangeNotification未覆盖的截图情况,使用UIApplication.userDidTakeScreenshotNotification做事后处理:
- 弹出提示告知用户View Once内容无法保存
- 若获得相册权限,删除刚生成的截图(减少敏感内容泄露风险)
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(handleScreenshotTaken), name: UIApplication.userDidTakeScreenshotNotification, object: nil ) } @objc private func handleScreenshotTaken() { // 显示提示弹窗 let alert = UIAlertController( title: "提示", message: "单次查看内容无法保存截图", preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) // 删除最新截图(需相册权限) deleteLatestScreenshot() } private func deleteLatestScreenshot() { guard PHPhotoLibrary.authorizationStatus() == .authorized else { return } let options = PHFetchOptions() options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] options.fetchLimit = 1 if let latestAsset = PHAsset.fetchAssets(with: .image, options: options).firstObject { PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.deleteAssets([latestAsset] as NSArray) }, completionHandler: { success, error in if let error = error { print("删除截图失败: \(error.localizedDescription)") } }) } }
3. 预加载遮罩优化感知
提前在View Once内容的视图层级中添加一个透明遮罩(alpha = 0),当检测到用户可能的截图操作(如长按屏幕,可通过UILongPressGestureRecognizer监听),立即将遮罩alpha设为1。利用iOS的UI刷新机制,遮罩会在截图快照生成前完成显示,让用户感觉是“实时触发”。
关键限制说明
- 没有公开API能100%覆盖所有截图场景,WhatsApp的实现也存在极小概率的漏判,但通过多信号组合已能满足绝大多数需求。
- 删除相册截图需要用户授权,且部分iOS版本可能限制该操作。
- 请勿使用私有API(如监听系统截图服务、硬件按键事件),否则会导致App被App Store拒绝。
内容的提问来源于stack exchange,提问作者Alexandru Motoc
相关产品推荐
相关产品推荐

