Запрет захвата экрана в приложении iOS
Из соображений безопасности мне нужно запретить захват экрана пользователями моего приложения. Содержимое, которое я отображаю, является конфиденциальным и не должно копироваться на устройство. Я видел один ответ на переполнение стека, но для Android.
Можно ли как-то в iOS предотвратить захват экрана?
Хотя захват скриншота в галерее нажатием нескольких кнопок является очень полезной функцией для пользователя, существует ограниченное требование, чтобы предотвратить это тоже. Есть указатели?
13 ответов
Я только что написал простое расширение UIView, которое позволяет скрыть его от захвата экрана, зеркалирования Airplay и так далее. Решение использует способность UITextField скрывать пароль от захвата.
extension UIView {
func makeSecure() {
let field = UITextField()
field.isSecureTextEntry = true
addSubview(field)
layer.superlayer?.addSublayer(field.layer)
field.layer.sublayers?.first?.addSublayer(layer)
}
}
с использованием:
class ViewController: UIViewController {
var secureView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
secureView.makeSecure()
}
}
Буду признателен, если кто-нибудь объяснит, как Apple творит эту магию внутри.
Там нет никакого способа, чтобы помешать делать скриншоты полностью. Вы можете делать то, что делает Snapchat, то есть требовать от пользователя прикосновения к экрану для просмотра любой отображаемой информации. Это потому, что событие снимка экрана системы прерывает касания. Это не идеальный метод, и вы не можете запретить пользователям делать скриншоты 100% времени.
Более подробная информация: iOS Скриншот обнаружения?
Другая проблема - это захват экрана в программном обеспечении - как человек снимает экран с помощью другого устройства, например камеры или другого телефона. Даже если вы запретите это в приложении, невозможно запретить кому-либо делать снимки экрана.
Одним из возможных путей решения проблемы является Yovo. Я только что видел это демо, которое взорвало мой разум!
Это чрезвычайно умный способ скрыть скриншот, и даже он частично обрабатывает случай "программного обеспечения", созданный JimBobBennet.
Вы устанавливаете маску размытия в верхней части изображения (в приложении используется шаблон забора, но подойдет любой шаблон) и перемещаете его с высокой скоростью. Если пользователь делает снимок экрана, он получает неподвижное изображение одного кадра, которое само по себе скрыто.
Он использует тот факт, что наш мозг может соединять изображение под движущейся маской - подобно тому, как вы можете "видеть сквозь" лопасти движущегося вентилятора.
Для того, чтобы захватить изображение, вам нужно будет записать его видео, что довольно хлопотно.
Единственная проблема здесь может быть IP - Yovo утверждает, что имеет более 300 патентов...
Прошло много времени, но я только что наткнулся на ScreenShieldKit, который является запатентованной технологией, используемой приложением для обмена сообщениями Confide. Что он делает, так это то, что он позволяет пользователю делать скриншоты, но содержимое на конечном изображении пустое. Недавно они выпустили версию для iOS.
Удалите конфиденциальную информацию из представлений, прежде чем перейти к фону. Когда приложение переходит в фоновый режим, система делает снимок главного окна приложения, который затем кратко представляет при переводе приложения обратно на передний план. Прежде чем вернуться из вашего applicationDidEnterBackground: метода, вы должны скрыть или скрыть пароли и другую конфиденциальную личную информацию, которая может быть захвачена как часть снимка.
В swift 4 добавьте этот код в ваш делегат приложения.
Объявите переменную в делегате приложения
var imageview : UIImageView?
func applicationWillResignActive(_ application: UIApplication) {
imageview = UIImageView.init(image: UIImage.init(named: "bg_splash"))
self.window?.addSubview(imageview!)
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidBecomeActive(_ application: UIApplication) {
if (imageview != nil){
imageview?.removeFromSuperview()
imageview = nil
}
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
Вот отличный пакет Swift, используемый для скрытия экрана со скриншотов системы и записи видео: SnapshotSafeView
Вы можете использовать это расширение ниже. Пожалуйста, примените этот метод к родительскому представлению
extension UIView {
func preventScreenshot(for view: UIView) {
let textField = UITextField()
textField.isSecureTextEntry = true
textField.isUserInteractionEnabled = false
guard let hiddenView = textField.layer.sublayers?.first?.delegate as? UIView else {
return
}
hiddenView.subviews.forEach { $0.removeFromSuperview() }
hiddenView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(hiddenView)
hiddenView.fillSuperview()
hiddenView.addSubview(view)
}
}
Так, например, чтобы предотвратить создание скриншотов в scrollView
private weak var scrollView: UIScrollView! (it's an outlet)
в вашем представленииDidLoad, просто сделайте это ниже
self.view.preventScreenshot(for: self.scrollView)
Примечание. fillSuperview просто привязывает ваше представление к своему суперпредставлению, как показано ниже:
NSLayoutConstraint.activate([
hiddenView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
hiddenView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
hiddenView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
hiddenView.topAnchor.constraint(equalTo: self.topAnchor)
])
Я слышал, что вы можете прослушать событие скриншота, используя UIApplicationUserDidTakeScreenshotNotification
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification
object:nil
queue:mainQueue
usingBlock:^(NSNotification *note) {
// executes after screenshot
NSLog(@"Screenshot Detection : %@", note);
UIAlertView *screenshotAlert = [[UIAlertView alloc] initWithTitle:@"Screenshot Detected" message:@"Oh Oh no screenshot bruhh" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[screenshotAlert show];
}];
Что делать, если вы могли сразу же удалить файл скриншота, когда он был сделан?
Вы можете запретить захват экрана и запись экрана для определенного представления в вашем приложении, используя это настраиваемое представление. Кроме того, вы можете добавить свой собственный заполнитель, который будет отображаться только тогда, когда пользователь попытается сделать снимок экрана или записать его.
import Foundation
import UIKit
class SecureView: UIView {
// placeholder will become visible when user try to capture screenshot
// or try to record the screen
private(set) var placeholderView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// add your content in this view
// it will be secure
private(set) var contentView: UIView = {
let hiddenView = UIView()
hiddenView.makeSecure()
hiddenView.translatesAutoresizingMaskIntoConstraints = false
return hiddenView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupView() {
self.addSubview(placeholderView)
self.addSubview(contentView)
NSLayoutConstraint.activate([
placeholderView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
placeholderView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
placeholderView.topAnchor.constraint(equalTo: self.topAnchor),
placeholderView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
contentView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
contentView.topAnchor.constraint(equalTo: self.topAnchor),
contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
])
}
}
extension UIView {
func makeSecure() {
DispatchQueue.main.async {
let field = UITextField()
field.isSecureTextEntry = true
self.addSubview(field)
field.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
field.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
self.layer.superlayer?.addSublayer(field.layer)
field.layer.sublayers?.first?.addSublayer(self.layer)
}
}
}
Пример проекта
Демо.gif
Вы можете этот инструмент. Он скрывает конфиденциальную информацию со скриншота.
Еще один крайний обходной путь, о котором я мог бы подумать, - это преобразовать ваше изображение в видеоформат и включить DRM. Затем вы можете зациклить "изображение" при его отображении, чтобы уменьшить размер файла.
Возможно, вы сможете обнаружить вновь сделанный снимок экрана и удалить его, если у приложения есть разрешение.
Однако, если вы хотите запретить пользователю делать скриншоты, содержащие конфиденциальную информацию, попробуйте обходной путь. Это не очень хорошая практика и не может полностью помешать пользователю сделать это.