You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:55:00