web-dev-qa-db-ja.com

applicationDidEnterBackgroundの前にビューまたはスプラッシュ画面を表示する(アクティブなビューのスクリーンショットを回避するため)

アプリに機密情報があるので、アプリをバックグラウンドに移動しようとしているときに、スプラッシュスクリーンでそれらを非表示にしたいと思います。

私はiOS6以降でアプリを実行します。

ビューをapplicationWillResignActiveで表示しようとしましたが、問題は、たとえばユーザーがコントロールパネルをスワイプしてもスプラッシュスクリーンが表示されることです。アプリがバックグラウンドに移動したときにのみ表示されるようにします。

applicationDidEnterBackgroundにsplashScreenを表示しようとしましたが、アニメーションの復元時に情報が表示される前にscreenShotが必要です。

ここに私が欲しいものの精神:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [_window addSubview:__splashController.view];
}
33
AncAinu

問題はあなたがsimulatorでテストしていることだと思います。デバイスでは、正常に動作するはずです。

私はこれをテストし、それはうまくいきました。アプリがバックグラウンドに入ったときにスプラッシュ画像を含む画像ビューを追加します-

- (void)applicationDidEnterBackground:(UIApplication *)application
{

        UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.window.bounds];

        imageView.tag = 101;    // Give some decent tagvalue or keep a reference of imageView in self
    //    imageView.backgroundColor = [UIColor redColor];
        [imageView setImage:[UIImage imageNamed:@"Default.png"]];   // assuming Default.png is your splash image's name

        [UIApplication.sharedApplication.keyWindow.subviews.lastObject addSubview:imageView];
}

アプリがフォアグラウンドに戻ったとき-

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    UIImageView *imageView = (UIImageView *)[UIApplication.sharedApplication.keyWindow.subviews.lastObject viewWithTag:101];   // search by the same tag value
    [imageView removeFromSuperview];

}

注-シミュレーター(iOS 7.0)では、ホームボタンを2回(Cmd + H)押してチェックすると、追加されたサブビューは表示されませんが、デバイスでは期待どおりに機能します(PaypalBofAアプリなど)。

編集:(追加情報)

iOS 7は、上記のようにサブビュー/ブラーを追加して機密情報を覆い隠す/置き換えることに加えて、内部のignoreSnapshotOnNextApplicationLaunchUIApplicationを介して画面のスナップショットを無視する機能を提供しますapplicationWillResignActiveまたはapplicationDidEnterBackground

UIApplication.h

// Indicate the application should not use the snapshot on next launch, even if there is a valid state restoration archive.
// This should only be called from methods invoked from State Preservation, else it is ignored.
- (void)ignoreSnapshotOnNextApplicationLaunch NS_AVAILABLE_IOS(7_0);

また、allowScreenShotフラグは Restrictions Payload で確認できます。

39
Ashok

Swift 3.0 Answer翻訳が面倒な人向け。

func applicationDidEnterBackground(_ application: UIApplication) {

    let imageView = UIImageView(frame: self.window!.bounds)
    imageView.tag = 101
    imageView.image = ...

    UIApplication.shared.keyWindow?.subviews.last?.addSubview(imageView)
 }

func applicationWillEnterForeground(_ application: UIApplication) {

    if let imageView : UIImageView = UIApplication.shared.keyWindow?.subviews.last?.viewWithTag(101) as? UIImageView {
        imageView.removeFromSuperview()
    }

}
8
SteffenK

同じ問題があり、本質的にapplicationDidEnterBackgroundを使用してコンテンツの上にUIWindowを表示していましたが、iOS8ではiOS7のように機能しませんでした。

私が見つけた解決策は、applicationWillResignActiveにUIWindowを作成することですが、それを非表示にするsecurityWindow.hidden = YES;そしてapplicationDidEnterBackgroundでは、securityWindow.hidden = NOを変更するだけです。

これは、NotificationCenterまたはControlPanelを使用するときにビューに影響を与えることなく、マルチタスク時にコンテンツを覆い隠すiOS7とまったく同じように機能するようです。

4
SharkBait

理由はわかりませんが、ここで説明する方法はどれもうまくいきませんでした。セキュリティ上の理由から、画面を隠そうとしただけです。だから、助けになったのはアップルからの技術的なQ&Aでした: https://developer.Apple.com/library/ios/qa/qa1838/_index.html

主な違いはUIViewControllerを使用していることでしょうか?とにかく、次のコードはIOS 9.1で完全に機能します。

- (void)applicationDidEnterBackground:(UIApplication *)application
{     
    UIViewController *blankViewController = [UIViewController new];
    blankViewController.view.backgroundColor = [UIColor blackColor];

    [self.window.rootViewController presentViewController:blankViewController animated:NO completion:NULL];
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [self.window.rootViewController dismissViewControllerAnimated:NO completion:NO];
}
2
Ertan D.

次のようにコードを記述する必要があります。

-(void)applicationWillResignActive:(UIApplication *)application
{
    imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
    [imageView setImage:[UIImage imageNamed:@"Portrait(768x1024).png"]];
    [self.window addSubview:imageView];
}

ここでimageviewを削除します:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(imageView != nil) {
        [imageView removeFromSuperview];
        imageView = nil;
    }
}

動作しており、適切にテストされています。

2
Deepak Kumar
@interface MyAppDelegate ()
@property (strong, nonatomic) MySplashView *splashView;
@end
@implementation MyAppDelegate
- (void)applicationWillResignActive:(UIApplication *)application {
    // hide keyboard and show a splash view
    [self.window endEditing:YES];
    MySplashView *splashView = [[MySplashView alloc] initWithFrame:self.window.bounds];
    [self.window addSubview:splashView];
    self.splashView = splashView;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
    // remove the splash view
    if (self.splashView) {
        [self.splashView removeFromSuperview];
        self.splashView = nil;
    }
}
@end
0
neoneye

これで解決しました。申し訳ありませんが、Xamarin.Formsですが、アイデアは理解できます。 xamarinではUIView.SnapshotView(true)を、iOSではUIView snapshotViewAfterScreenUpdatesを呼び出す必要があります。 iOS7およびiOS8のDidEnterBackgroundで動作します。

public override void DidEnterBackground(UIApplication uiApplication)
{
    App.Current.MainPage = new DefaultPage();
    **UIApplication.SharedApplication.KeyWindow.SnapshotView(true);**
    base.DidEnterBackground(uiApplication);
}
0
shane

これはSwift 3.0に役立つと思います

func applicationWillResignActive(_ application: UIApplication) {

        let imageView = UIImageView(frame: self.window!.bounds)
        imageView.tag = 101
        imageView.backgroundColor = UIColor.white
        imageView.contentMode = .center
        imageView.image = #image#
        UIApplication.shared.keyWindow?.subviews.last?.addSubview(imageView)

    }

func applicationWillEnterForeground(_ application: UIApplication) {
        ReachabilityManager.shared.stopMonitoring()
        if let imageView : UIImageView = UIApplication.shared.keyWindow?.subviews.last?.viewWithTag(101) as? UIImageView {
            imageView.removeFromSuperview()
        }
    }
0
Blahji