The app Snapchat, on the App Store, is an app that lets you share pictures with a self-destruct on them. You can only view the pics for X seconds. If you attempt to take a screenshot while the picture is showing using the home-power key combo, it will tell the sender you tried to take a screenshot.
What part of the SDK lets you detect that the user is taking a screenshot? I did not know this was possible.
This question is related to
ios
screenshot
As of iOS 7 the other answers are no longer true. Apple has made it so touchesCancelled:withEvent:
is no longer called when the user takes a screenshot.
This would effectively break Snapchat entirely, so a couple betas in a new solution was added. Now, the solution is as simple as using NSNotificationCenter to add an observer to UIApplicationUserDidTakeScreenshotNotification.
Here's an example:
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification
object:nil
queue:mainQueue
usingBlock:^(NSNotification *note) {
// executes after screenshot
}];
NotificationCenter.default.addObserver(
forName: UIApplication.userDidTakeScreenshotNotification,
object: nil,
queue: .main) { notification in
//executes after screenshot
}
Swift 4+
NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: OperationQueue.main) { notification in
//you can do anything you want here.
}
by using this observer you can find out when user takes a screenshot, but you can not prevent him.
Swift 4 Examples
Example #1 using closure
NotificationCenter.default.addObserver(forName: .UIApplicationUserDidTakeScreenshot,
object: nil,
queue: OperationQueue.main) { notification in
print("\(notification) that a screenshot was taken!")
}
Example #2 with selector
NotificationCenter.default.addObserver(self,
selector: #selector(screenshotTaken),
name: .UIApplicationUserDidTakeScreenshot,
object: nil)
@objc func screenshotTaken() {
print("Screenshot taken!")
}
Latest SWIFT 3:
func detectScreenShot(action: @escaping () -> ()) {
let mainQueue = OperationQueue.main
NotificationCenter.default.addObserver(forName: .UIApplicationUserDidTakeScreenshot, object: nil, queue: mainQueue) { notification in
// executes after screenshot
action()
}
}
In viewDidLoad, call this function
detectScreenShot { () -> () in
print("User took a screen shot")
}
However,
NotificationCenter.default.addObserver(self, selector: #selector(test), name: .UIApplicationUserDidTakeScreenshot, object: nil)
func test() {
//do stuff here
}
works totally fine. I don't see any points of mainQueue...
Heres how to do in Swift with closures:
func detectScreenShot(action: () -> ()) {
let mainQueue = NSOperationQueue.mainQueue()
NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationUserDidTakeScreenshotNotification, object: nil, queue: mainQueue) { notification in
// executes after screenshot
action()
}
}
detectScreenShot { () -> () in
print("User took a screen shot")
}
Swift 4.2
func detectScreenShot(action: @escaping () -> ()) {
let mainQueue = OperationQueue.main
NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: mainQueue) { notification in
// executes after screenshot
action()
}
}
This is included as a standard function in:
https://github.com/goktugyil/EZSwiftExtensions
Disclaimer: Its my repo
Looks like there are no direct way to do this to detect if user has tapped on home + power button
. As per this, it was possible earlier by using darwin notification, but it doesn't work any more. Since snapchat is already doing it, my guess is that they are checking the iPhone photo album to detect if there is a new picture got added in between this 10 seconds, and in someway they are comparing with the current image displayed. May be some image processing is done for this comparison. Just a thought, probably you can try to expand this to make it work. Check this for more details.
Edit:
Looks like they might be detecting the UITouch cancel event(Screen capture cancels touches) and showing this error message to the user as per this blog: How to detect screenshots on iOS (like SnapChat)
In that case you can use – touchesCancelled:withEvent:
method to sense the UITouch cancellation to detect this. You can remove the image in this delegate method and show an appropriate alert to the user.
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
NSLog(@"Touches cancelled");
[self.imageView removeFromSuperView]; //and show an alert to the user
}
Source: Stackoverflow.com