Отображать представление или экран-заставку перед applicationDidEnterBackground (чтобы избежать скриншота активного представления)

У меня есть конфиденциальная информация в моем приложении, поэтому я хотел бы скрыть ее с помощью заставки, когда приложение будет перемещено в фоновый режим.

Я запускаю приложение на iOS6 и выше.

Я попытался отобразить представление в applicationWillResignActive, но проблема в том, что он отображает заставку, даже когда пользователь, например, проводит пальцем по панели управления. Я хочу, чтобы он отображался только тогда, когда приложение перемещается в фоновый режим.

Я попытался отобразить свой заставку в applicationDidEnterBackground, но он делает снимок экрана раньше, поэтому информация отображается при восстановлении во время анимации.

Вот дух того, что я хочу:

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

person Tancrede Chazallet    schedule 05.11.2013    source источник
comment
Насколько я знаю, вам нужно выполнить действие внутри applicationWillResignActive и отменить то же действие applicationDidBecomeActive из UIApplicationDelegate методов.   -  person Ashok    schedule 05.11.2013
comment
Проблема в том, что если я показываю заставку в applicationWillResignActive, то она отображается всякий раз, когда пользователь просто смотрит на свою панель управления или дважды нажимает кнопку «Домой»…   -  person Tancrede Chazallet    schedule 05.11.2013
comment
Paypal Приложение для iOS делает что-то подобное, они размывают свой последний активный вид, когда приложение переходит в фоновый режим (для защиты информации о пользователе). Я бы порекомендовал вам изучить это или некоторые другие приложения. РЕДАКТИРОВАТЬ: я только что заметил, что PayPal не размывается, когда открывается панель управления, поэтому я считаю, что есть какой-то способ, поэтому то, чего вы пытаетесь достичь, должно быть осуществимо. Буду следить за этой веткой.   -  person Ashok    schedule 05.11.2013
comment
Это то, что я хочу сделать (поскольку мое приложение также имеет дело с банковской информацией), но я не уверен, что PayPal позволит мне увидеть его код:/   -  person Tancrede Chazallet    schedule 05.11.2013
comment
Я думаю, что решение @Ashok, вероятно, лучшее. Когда пользователь дважды нажимает, получает вызов, вызывает панель управления, отказывается от приложения, скорее всего, ему все равно, что показывает ваше приложение, поскольку оно делает это плавно и круто.   -  person Andrea    schedule 05.11.2013
comment
@Andrea - Но то, что он ищет, должно быть осуществимо, поскольку многие другие финансовые (защищенные) приложения, такие как Paypal, BofA, делают то же самое. (Примечание — на iPad — центр управления, центр уведомлений и т. д. частично закрывают приложение). Я думаю, что решение не сложное, но мне оно просто не подходит. Давайте проголосуем за этот вопрос, чтобы привлечь внимание сюда :). Также @AncAinu - вы должны попробовать свое решение на реальном устройстве (а не только на симуляторе), если это еще не сделано.   -  person Ashok    schedule 05.11.2013
comment
Метод @Ashok - это то, что я ищу. Безопасный метод приложения, при котором любое переключение приложений скрывает основной вид и вместо этого показывает экран-заставку.   -  person jowie    schedule 15.07.2015


Ответы (8)


Я думаю, проблема в том, что вы тестируете в симуляторе. На устройстве должно работать нормально.

Я проверил это, и это сработало. Добавьте изображение с заставкой, когда приложение входит в фоновый режим -

- (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) добавленное подпредставление не отображается, когда вы проверяете, дважды нажав кнопку «Домой» (Cmd + H), но на устройстве оно работает должным образом (например, приложения paypal, BofA)

EDIT: (Дополнительная информация)

В дополнение к сокрытию/замене конфиденциальной информации путем добавления подвида/размытия, как описано выше, iOS 7 предоставляет вам возможность игнорировать снимок экрана через ignoreSnapshotOnNextApplicationLaunch из UIApplication внутри 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 можно изучить в Полезная нагрузка ограничений.

person Ashok    schedule 05.11.2013
comment
Да, это был день, когда моя молния умерла... Действительно, она отлично работает на настоящем устройстве. - person Tancrede Chazallet; 06.11.2013
comment
Это работает, за исключением случаев, когда воспроизводится видео. Я могу скрыть, какое видео воспроизводилось? - person MwcsMac; 22.04.2015

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

}
person SteffenK    schedule 28.02.2017

Была та же проблема, по сути, я использовал applicationDidEnterBackground для отображения UIWindow поверх содержимого, но в iOS8 это не работало, как в iOS7.

Решение, которое я нашел, состояло в том, чтобы создать UIWindow в applicationWillResignActive, но сделать его скрытым securityWindow.hidden = YES; а затем в applicationDidEnterBackground все, что я сделал бы, это изменил бы securityWindow.hidden = NO.

Кажется, это работает точно так же, как iOS7, скрывая содержимое при многозадачности, не влияя на представление при использовании NotificationCenter или ControlPanel.

person SharkBait    schedule 11.11.2014
comment
Это именно то, что мне нужно. Протестировано на iOS7 через iOS9. - person Vilém Kurz; 22.10.2015

Не знаю почему, но ни один из описанных здесь способов мне не помог. Я просто пытался закрыть экран из соображений безопасности. Итак, что помогло, так это технические вопросы и ответы от Apple: 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];
}
person Ertan D.    schedule 15.12.2015
comment
Если отображается предупреждение, оно не будет скрыто, как мы можем скрыть предупреждение в фоновом режиме - person Arshad Shaik; 08.08.2019
comment
Осторожно с этим; если у вас есть модальное окно, представленное в вашем текущем окне, и метод presentViewController не завершается, когда вы вернетесь на передний план, ваше модальное окно может быть закрыто. - person Huy-Anh Hoang; 06.09.2019

Нужно написать код следующим образом:

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

Здесь, чтобы удалить изображение:

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

Он работает и должным образом протестирован.

person Deepak Kumar    schedule 29.10.2014

Я думаю, это поможет 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()
        }
    }
person Balaji Malliswamy    schedule 28.03.2017

Это исправило это для меня, извините, это для Xamarin.Forms, но вы должны получить эту идею. Вам нужно вызвать UIView.SnapshotView(true) в xamarin или UIView snapshotViewAfterScreenUpdates в iOS. Работает в DidEnterBackground на iOS7 и iOS8:

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

person    schedule
comment
что вы делаете, если на экране отображается какое-то системное предупреждение. в этом случае MySplashView также отображается на экране. могу ли я этого избежать? - person Klemen; 14.06.2017