如何在用户截屏前对UIView进行遮罩处理?
iOS 截屏前添加遮罩的可行方案
你之前的代码失效是因为UIApplication.userDidTakeScreenshotNotification是截屏完成后才触发的通知,这时候添加遮罩根本赶不上被截进图里,自然没用。下面是两种可靠的实现思路:
方法1:利用系统截屏动作回调(推荐)
iOS在准备执行系统截屏操作时,会调用UIWindowSceneDelegate的windowScene(_:performActionFor:completionHandler:)方法,动作类型为UIWindowScene.ActionType.screenshot,这是目前能提前拦截截屏的最可靠时机。
实现示例(ViewController内处理)
首先让你的ViewController遵守UIWindowSceneDelegate,然后添加如下逻辑:
override func viewDidLoad() { super.viewDidLoad() // 绑定当前windowScene的代理到ViewController if let windowScene = view.window?.windowScene { windowScene.delegate = self } } // 实现UIWindowSceneDelegate的截屏动作处理方法 extension YourViewController: UIWindowSceneDelegate { func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { // 判断是否是系统截屏动作 guard shortcutItem.type == UIWindowScene.ActionType.screenshot.rawValue else { completionHandler(false) return } // 立即添加遮罩视图 addMaskView() // 告诉系统继续完成截屏操作 completionHandler(true) // 截屏完成后移除遮罩(延迟0.1秒确保系统操作完成) DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.removeMaskView() } } }
实现示例(SceneDelegate内处理)
如果想在全局统一处理,也可以在SceneDelegate中实现该方法:
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { if shortcutItem.type == UIWindowScene.ActionType.screenshot.rawValue { // 创建并添加全屏遮罩 let maskView = UIView(frame: windowScene.coordinateSpace.bounds) maskView.backgroundColor = .black // 自定义遮罩样式 maskView.tag = 999 windowScene.windows.first?.addSubview(maskView) completionHandler(true) // 移除遮罩 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { windowScene.windows.first?.viewWithTag(999)?.removeFromSuperview() } return } completionHandler(false) }
注意事项
- 该方法只能拦截系统自带的截屏操作(电源+音量键、控制中心截屏按钮),无法拦截第三方工具(如录屏后截图、第三方截屏APP)的操作,这是iOS系统权限限制导致的,没有完美解决方案。
- 延迟移除遮罩的时间不宜过长,0.1秒足够确保系统完成截屏,过长会影响用户体验。
内容的提问来源于stack exchange,提问作者cleanrun
相关产品推荐
相关产品推荐

