Запрет захвата экрана в приложении 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. Я только что видел это демо, которое взорвало мой разум!

http://vimeo.com/108244650

Это чрезвычайно умный способ скрыть скриншот, и даже он частично обрабатывает случай "программного обеспечения", созданный 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

Вы можете этот инструмент. Он скрывает конфиденциальную информацию со скриншота.

https://screenshieldkit.com

Еще один крайний обходной путь, о котором я мог бы подумать, - это преобразовать ваше изображение в видеоформат и включить DRM. Затем вы можете зациклить "изображение" при его отображении, чтобы уменьшить размер файла.

Возможно, вы сможете обнаружить вновь сделанный снимок экрана и удалить его, если у приложения есть разрешение.

Однако, если вы хотите запретить пользователю делать скриншоты, содержащие конфиденциальную информацию, попробуйте обходной путь. Это не очень хорошая практика и не может полностью помешать пользователю сделать это.

Другие вопросы по тегам