For some reasons, we may want to prevent users from taking screenshots of our app. However, iOS does not provide such functionality. Fortunately, we can use UITextField to achieve this effect.
After setting UITextField.isSecureTextEntry to true, if the user takes a screenshot, iOS UITextField will clear its content to protect its content from being screenshotted. Therefore, if we put the current view into UITextField, when the user takes a screenshot, UITextField will prevent the current view from being screenshotted, as shown in the following code (this code comes from here).
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.makeSecure() } } 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) } } }
When we use the above code to protect the current view, if the user takes a screenshot of this view, he or she will only get a picture that is all black.
After using makeSecure() to protect the view, you can also use makeInsecure() to unprotect the view at any time, as shown in the following code.
class ViewController: UIViewController { @IBAction func onClick(_ sender: Any) { view.makeInsecure() } override func viewDidLoad() { super.viewDidLoad() view.makeSecure() } } var textField: UITextField? 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) textField = field } } func makeInsecure() { DispatchQueue.main.async { guard let field = textField else { return } textField = nil field.layer.superlayer?.addSublayer(self.layer) field.removeFromSuperview() field.layer.removeFromSuperlayer() } } }