web-dev-qa-db-ja.com

スクリーンショットのiOS検出?

アプリ Snapchat は、App Storeで、写真を自己破壊して共有できるアプリです。写真はX秒間のみ表示できます。ホームパワーキーコンボを使用して写真が表示されているときにスクリーンショットを撮ろうとすると、スクリーンショットを撮ろうとしたことが送信者に通知されます。

ユーザーがスクリーンショットを撮影していることをSDKのどの部分で検出できますか?これが可能だとは知りませんでした。

124
me2

答えが見つかりました!!スクリーンショットを撮ると、画面上のタッチが中断されます。これが、snapchatが写真を見るために保持する必要がある理由です。参考: http://tumblr.jeremyjohnstone.com/post/38503925370/how-to-detect-screenshots-on-ios-like-snapchat

22

IOS 7以降、他の答えは当てはまりません。 Appleが作成したため、ユーザーがスクリーンショットを撮ったときにtouchesCancelled:withEvent:が呼び出されなくなりました。

これにより、Snapchatは事実上完全に破損するため、新しいソリューションにいくつかのベータ版が追加されました。これで、NSNotificationCenterを使用して IApplicationUserDidTakeScreenshotNotification にオブザーバーを追加するのと同じくらい簡単に解決できます。

次に例を示します。

客観的C

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification
                                                  object:nil
                                                   queue:mainQueue
                                              usingBlock:^(NSNotification *note) {
                                                 // executes after screenshot
                                              }];

Swift

NotificationCenter.default.addObserver(
    forName: .UIApplicationUserDidTakeScreenshot,
    object: nil,
    queue: .main) { notification in
        //executes after screenshot
}
346
Mick MacCallum

Swiftでクロージャを使用する方法は次のとおりです。

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()
    }
}

これは、次の標準機能として含まれています。

https://github.com/goktugyil/EZSwiftExtensions

免責事項:その私のレポ

11
Esqarrouth

最新Swift

func detectScreenShot(action: @escaping () -> ()) {
        let mainQueue = OperationQueue.main
        NotificationCenter.default.addObserver(forName: .UIApplicationUserDidTakeScreenshot, object: nil, queue: mainQueue) { notification in
            // executes after screenshot
            action()
        }
    }

viewDidLoadで、この関数を呼び出します

detectScreenShot { () -> () in
 print("User took a screen shot")
}

しかしながら、

NotificationCenter.default.addObserver(self, selector: #selector(test), name: .UIApplicationUserDidTakeScreenshot, object: nil)

    func test() {
    //do stuff here
    }

まったく問題なく動作します。 mainQueueのポイントが表示されません...

4
Maksim Kniazev

ユーザーがhome + power buttonをタップしたかどうかを検出する直接的な方法はないようです。 this に従って、以前はdarwin通知を使用することで可能になりましたが、もう機能しません。 snapchatはすでにそれを行っているので、私の推測では、iPhoneフォトアルバムをチェックして、この10秒の間に追加された新しい画像があるかどうかを検出し、何らかの形で表示されている現在の画像と比較しています。この比較のために画像処理が行われている可能性があります。ちょっと考えてみて、おそらくこれを拡張して機能させることができます。 詳細はこちら を確認してください。

編集:

UITouchキャンセルイベント(スクリーンキャプチャがタッチをキャンセルする)を検出し、このブログに従ってユーザーにこのエラーメッセージを表示しているようです: iOS(SnapChatなど)でスクリーンショットを検出する方法

その場合、– touchesCancelled:withEvent:メソッドを使用してUITouchのキャンセルを検知し、これを検出できます。このデリゲートメソッドで画像を削除し、ユーザーに適切なアラートを表示できます。

- (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
}
1
iDev

Swift 4の例

例#1クロージャを使用する

NotificationCenter.default.addObserver(forName: .UIApplicationUserDidTakeScreenshot, 
                                       object: nil, 
                                       queue: OperationQueue.main) { notification in
    print("\(notification) that a screenshot was taken!")
}

セレクターを使用した例#2

NotificationCenter.default.addObserver(self, 
                                       selector: #selector(screenshotTaken), 
                                       name: .UIApplicationUserDidTakeScreenshot, 
                                       object: nil)

@objc func screenshotTaken() {
    print("Screenshot taken!")
}
0
Devbot10