W Przygotowanie UI aby działać w tle , Apple mówi:
Przygotuj swój interfejs użytkownika na migawkę aplikacji
W pewnym momencie po tym, jak aplikacja przejdzie w tło i powróci metoda delegata, UIKit wykonuje migawkę bieżącego interfejsu użytkownika aplikacji. System wyświetla wynikowy obraz w przełączniku aplikacji. Wyświetla również obraz tymczasowo podczas przenoszenia aplikacji z powrotem na pierwszy plan.
Interfejs użytkownika aplikacji nie może zawierać żadnych poufnych informacji o użytkowniku, takich jak hasła czy numery kart kredytowych. Jeśli twój interfejs zawiera takie informacje, usuń je ze swoich widoków podczas przechodzenia w tło. Odrzuć także alerty, tymczasowe interfejsy i kontrolery widoku systemu, które zasłaniają zawartość aplikacji. Migawka przedstawia interfejs aplikacji i powinna być rozpoznawalna dla użytkowników. Gdy aplikacja wróci na pierwszy plan, możesz odpowiednio przywrócić dane i widoki.
Widzieć Pytania i odpowiedzi techniczne QA1838: Zapobieganie pojawianiu się poufnych informacji w przełączniku zadań
Oprócz ukrywania / zastępowania poufnych informacji możesz również powiedzieć systemowi iOS 7, aby nie wykonywał migawki ekranu za pośrednictwem ignoreSnapshotOnNextApplicationLaunch
, którego dokumentacja mówi:
Jeśli uważasz, że migawka nie może poprawnie odzwierciedlać interfejsu użytkownika aplikacji po ponownym uruchomieniu aplikacji, możesz zadzwonić, ignoreSnapshotOnNextApplicationLaunch
aby zapobiec wykonaniu tego obrazu migawki.
To powiedziawszy, wygląda na to, że zrzut ekranu jest nadal wykonywany i dlatego złożyłem raport o błędzie. Ale powinieneś przetestować dalej i sprawdzić, czy użycie tego ustawienia pomaga.
Jeśli była to aplikacja dla przedsiębiorstw, warto również przyjrzeć się odpowiedniemu ustawieniu allowScreenShot
opisanemu w sekcji Obciążenie ograniczeń w dokumencie Odwołanie do profilu konfiguracji.
Oto implementacja, która osiąga to, czego potrzebowałem. Możesz przedstawić własny UIImageView
wzorzec lub użyć wzorca protokołu delegata, aby ukryć poufne informacje:
// SecureDelegate.h
#import <Foundation/Foundation.h>
@protocol SecureDelegate <NSObject>
- (void)hide:(id)object;
- (void)show:(id)object;
@end
Następnie przekazałem delegatowi mojej aplikacji właściwość:
@property (weak, nonatomic) id<SecureDelegate> secureDelegate;
Mój kontroler widoku ustawia to:
- (void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
delegate.secureDelegate = self;
}
Kontroler widoku oczywiście implementuje ten protokół:
- (void)hide:(id)object
{
self.passwordLabel.alpha = 0.0;
}
- (void)show:(id)object
{
self.passwordLabel.alpha = 1.0;
}
I wreszcie, mój delegat aplikacji korzysta z tego protokołu i właściwości:
- (void)applicationWillResignActive:(UIApplication *)application
{
[application ignoreSnapshotOnNextApplicationLaunch]; // this doesn't appear to work, whether called here or `didFinishLaunchingWithOptions`, but seems prudent to include it
[self.secureDelegate hide:@"applicationWillResignActive:"]; // you don't need to pass the "object", but it was useful during my testing...
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[self.secureDelegate show:@"applicationDidBecomeActive:"];
}
Uwaga, używam applicationWillResignActive
raczej niż zalecanaapplicationDidEnterBackground
, ponieważ, jak zauważyli inni, ten ostatni nie jest wywoływany po dwukrotnym dotknięciu przycisku głównego, gdy aplikacja jest uruchomiona.
Chciałbym móc używać powiadomień do obsługi tego wszystkiego, zamiast wzorca delegata-protokołu, ale w moich ograniczonych testach powiadomienia nie są obsługiwane w odpowiednim czasie, ale powyższy wzorzec działa dobrze.