04.iOS截屏防护方案

前言

想必很多同学都有遇到过或者想过怎么能防止系统截图,但通过大量的搜索并没有找到具体的实现方案。

一、 常见方案

1.1 系统通知

UIApplication.userDidTakeScreenshotNotification 这个系统通知是在完成截屏动作后,系统给到 App 的,在收到这个通知后做处理,并不能达到防护的效果。

微信的付款吗就是这样的实现,在截屏后提供一个警示内容。

1.2 小红书

在使用小红书的截屏的时候顶部状态栏会添加一个小红书的水印如下图:

它是怎么实现的呢?我有两个猜测:

第一种:水印一直在,刘海后面

因为非刘海屏没有这个水印,所以估计是这样,但是通过切换到任务管理器状态并没有看到有那个水印。

第二种:通过什么黑科技加上的?

不是第一种,难道真的是又什么黑科技?

继续验证

我觉得肯定是第一种,觉得任务切换的状态下是不是那个水印被系统隐藏掉。想道还有 QuickTime 可以投屏来验证。

破案,果然是藏在刘海后面的,没有继续深入的价值了🤷‍♂️。

1.3 ScreenShieldKit

在寻找解决方案的时候发现了这样一个SDK ScreenShieldKit

Contact us for more information and to receive a free evaluation SDK!

这句话一看就是收钱的了,抱着能白嫖绝不三连的宗旨,先略过暂不深入研究。(开玩笑,如果你觉得我的方案不错,本文求赞评转+Star!)

1.4 爱奇艺

爱奇艺使用的是截图后直接读取用户相册删除图片的方式进行的,不给权限,截图就不会被删除。

1.5 UITextField

当我们将一个 UITextFieldisSecureTextEntry 设置为 true 的时候,会隐去输入的文案用 圆点 替代。并且在进行录屏或者截屏的时候都会被系统隐去。

下面用我的个人项目 梦见账本

如下图我正在用 QuickTime 进行录屏:

那么我们是否可以使用这种特性呢?

二、 RyukieSwifty/ScreenShield

基于 UITextField 的效果我实现了一个 ScreenShieldView 可以很方便的进行使用。

GitHub: RyukieSwifty/ScreenShield

如果觉得不错的话,欢迎留个⭐️哦

2.1 使用方式

Cocoapods 导入

pod 'RyukieSwifty/ScreenShield'

使用

例如对整个控制器的 View 进行截屏防护:

import UIKit
import RyukieSwifty

class TransactionAddViewController: UIViewController {
    // MARK: - Life
    override func loadView() {
        view = ScreenShieldView.create()
    }
    ...
}

2.2 如何实现的

按照向里面添加子视图的方式验证具体的原因,最后发现这个效果是由一个私有类实现的 _UITextLayoutCanvasView 。他本质上也是一个 UIView ,所以理论上只要我们能够创建出来一个它,那么就可以将想要保护的内容添加进去。

由于它是私有类,无法直接创建,并且如果直接通过字符串区创建也担心有审核风险,于是我通过下面的方式来创建。

private func makeSecureView() -> UIView? {
    let field = UITextField()
    field.isSecureTextEntry = true
    let fv = field.subviews.first
    fv?.subviews.forEach { $0.removeFromSuperview() }
    fv?.isUserInteractionEnabled = true
    return fv
}

当前手头没有更多的系统版本设备可以测试,已经验证的 13.7 ~ 15.3.1 是没问题的。

不排除会存在某些版本上 UITextField 的结构发生了调整导致失效的问题,如果有,欢迎在 GitHubissue

总结

不知道各位有没有其他的实现方式,有的话欢迎一起交流。

如果本文有帮到你,欢迎赞评转+Star!

Last updated