Prevent screen capture in an iOS app
I've just wrote simple extension of UIView that allows to hide it from screen-capturing, Airplay mirroring and so on. The solution uses ability of UITextField to hide a password from capturing.
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)
}
}
}
using:
class ViewController: UIViewController {
var secureView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
secureView.makeSecure()
}
}
I'll be grateful if someone explains how Apple does this magic inside.
There's no way to prevent taking screenshots entirely. You can do what Snapchat does, which is by requiring the user to be touching the screen to view whatever information you're displaying. This is because the system screenshot event interrupts touches. It's not a perfect method and you can't prevent users from taking screenshots 100% of the time.
More details: iOS Detection of Screenshot?
It's been a while, but I just came across ScreenShieldKit, which is a patent-pending technology used by the messaging app Confide. What it does is that it let's the user take screenshots, but the content is blank on the end picture. They recently released the iOS version.
Remove sensitive information from views before moving to the background. When an application transitions to the background, the system takes a snapshot of the application’s main window, which it then presents briefly when transitioning your application back to the foreground. Before returning from your applicationDidEnterBackground: method, you should hide or obscure passwords and other sensitive personal information that might be captured as part of the snapshot.
In swift 4 add this code to your app delegate.
Declare a variable in app delegate
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.
}
I've heard that you can listen for a screenshot event using 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];
}];
what if you could immediately delete the screenshot file when it was made?