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

iOS应用运行时阻止截屏问题:监听UIApplicationUserDidTakeScreenshot通知无效

嘿,我来帮你梳理下这个问题——首先得明确:iOS并没有官方提供直接阻止用户截屏的API,因为这是系统级别的操作,苹果更倾向于保障用户的操作权限。不过我们可以先解决你当前的检测问题,再给你几个实现类似“阻止”效果的替代方案。

一、先修正你的截屏检测代码

你当前的代码有个小问题:定义了mainQueue变量,但后面传的是未定义的queue,导致观察者可能没正确绑定。另外,现在Swift有更简洁的语法调用这个通知,修正后的代码如下:

// 在合适的时机(比如viewDidLoad)添加观察者
NotificationCenter.default.addObserver(
    forName: UIApplication.userDidTakeScreenshotNotification,
    object: nil,
    queue: .main
) { _ in
    // 这里是截屏完成后的回调
    print("用户刚完成了截屏操作!")
    // 你可以在这里做后续处理,比如弹出提示告知用户该内容不允许截屏
}

注意:这个通知是截屏完成后才触发的,所以它只能告诉你用户已经截屏了,没法提前阻止。

二、更及时的屏幕捕获检测(覆盖截屏+录屏)

如果你想在截屏动作开始时就做出响应(而不是等截屏完成),可以使用UIScreen.main.isCaptured属性,它能实时检测屏幕是否被录制或截屏。用KVO监听这个属性的变化:

class YourViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 添加KVO观察者
        UIScreen.main.addObserver(
            self,
            forKeyPath: #keyPath(UIScreen.isCaptured),
            options: .new,
            context: nil
        )
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard keyPath == #keyPath(UIScreen.isCaptured),
              let isCaptured = change?[.newKey] as? Bool else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }
        
        if isCaptured {
            // 屏幕被捕获(截屏/录屏开始),立刻隐藏敏感内容或显示模糊层
            showContentProtectionOverlay()
        } else {
            // 捕获结束,恢复正常内容
            hideContentProtectionOverlay()
        }
    }
    
    // 页面销毁时移除观察者,避免内存泄漏
    deinit {
        UIScreen.main.removeObserver(self, forKeyPath: #keyPath(UIScreen.isCaptured))
    }
    
    // 示例:显示模糊覆盖层
    private func showContentProtectionOverlay() {
        let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
        blurView.frame = view.bounds
        blurView.tag = 999
        view.addSubview(blurView)
    }
    
    private func hideContentProtectionOverlay() {
        view.subviews.first(where: { $0.tag == 999 })?.removeFromSuperview()
    }
}

这个方法的响应速度比通知快得多,能在截屏动作触发的瞬间就覆盖内容,大大降低敏感内容被截到的概率。

三、关于“阻止截屏”的替代方案

因为iOS不允许App直接拦截系统截屏操作,所以我们只能通过以下方式实现类似效果:

  • 实时内容保护:上面提到的isCaptured监听方案,在屏幕被捕获时立刻用模糊层、纯色层或占位图覆盖敏感内容。
  • 截屏后补救:在收到userDidTakeScreenshotNotification后,可尝试删除相册中的截屏(但需要相册权限,且苹果审核可能质疑该行为,谨慎使用)。
  • 用户引导:在敏感页面明确告知用户该内容不允许截屏,从行为层面减少截屏操作。

最后提醒:不要用过于激进的手段(比如频繁弹窗、强制退出App等)阻止截屏,这会违反苹果审核政策,导致App被拒。

内容的提问来源于stack exchange,提问作者Bansi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:02:30