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

如何防止UIDocumentInteractionController中打开的文档被截屏?

解决UIDocumentInteractionController预览文档防截屏问题

UIDocumentInteractionController的预览视图由系统完全托管,常规的UIView安全层方案无法直接作用于它,你可以尝试以下几种可行方案:

方案1:改用QLPreviewController并添加安全层

QLPreviewController的视图层级可被我们获取和修改,能让安全层逻辑生效。

class PreviewVC: UIViewController, QLPreviewControllerDataSource, QLPreviewControllerDelegate {
    var documentURL: URL!
    
    func showDocument() {
        let previewController = QLPreviewController()
        previewController.dataSource = self
        previewController.delegate = self
        present(previewController, animated: true)
    }
    
    // QLPreviewController数据源实现
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        return 1
    }
    
    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        return documentURL as QLPreviewItem
    }
    
    // 预览出现后给视图加安全层
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        presentedViewController?.view?.makeSecure()
    }
    
    // 复用你的安全层扩展
    extension UIView {
        func makeSecure() {
            DispatchQueue.main.async {
                let secureField = UITextField()
                secureField.isSecureTextEntry = true
                self.addSubview(secureField)
                secureField.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
                secureField.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
                self.layer.superlayer?.addSublayer(secureField.layer)
                secureField.layer.sublayers?.first?.addSublayer(self.layer)
            }
        }
    }
}

方案2:监听截屏通知,即时遮挡内容

如果坚持用UIDocumentInteractionController,可以监听系统截屏通知,触发时立即显示遮挡层,让截屏内容失效:

class PreviewVC: UIViewController, UIDocumentInteractionControllerDelegate {
    var docOpener: UIDocumentInteractionController!
    private var blurOverlay: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册截屏通知
        NotificationCenter.default.addObserver(self, selector: #selector(onScreenshotTaken), name: UIApplication.userDidTakeScreenshotNotification, object: nil)
        
        // 创建全屏遮挡层
        blurOverlay = UIView(frame: view.bounds)
        blurOverlay.backgroundColor = .black
        blurOverlay.alpha = 0
        blurOverlay.isUserInteractionEnabled = false
        view.addSubview(blurOverlay)
    }
    
    @objc private func onScreenshotTaken() {
        // 显示遮挡层,1秒后隐藏
        UIView.animate(withDuration: 0.1) {
            self.blurOverlay.alpha = 1
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            UIView.animate(withDuration: 0.1) {
                self.blurOverlay.alpha = 0
            }
        }
    }
    
    // 原文档展示逻辑
    func showDocument(at path: URL) {
        docOpener = UIDocumentInteractionController(url: path)
        docOpener.delegate = self
        docOpener.presentPreview(animated: true)
    }
    
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }
}

方案3:自定义文档渲染(针对PDF等格式)

如果文档是PDF或其他可自定义渲染的类型,直接用自定义视图(比如PDFView、WKWebView)渲染内容,再给视图加安全层:

class PreviewVC: UIViewController {
    var documentURL: URL!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let pdfView = PDFView(frame: view.bounds)
        pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        if let pdfDoc = PDFDocument(url: documentURL) {
            pdfView.document = pdfDoc
        }
        view.addSubview(pdfView)
        // 给渲染视图加安全层
        pdfView.makeSecure()
    }
    
    extension UIView {
        func makeSecure() {
            DispatchQueue.main.async {
                let secureField = UITextField()
                secureField.isSecureTextEntry = true
                self.addSubview(secureField)
                secureField.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
                secureField.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
                self.layer.superlayer?.addSublayer(secureField.layer)
                secureField.layer.sublayers?.first?.addSublayer(self.layer)
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:05:32