在Preparing Your UI to Run in the Background,Apple 说:
为应用快照准备 UI
在您的应用程序进入后台并且您的委托方法返回后的某个时间点,UIKit 会拍摄您应用程序当前用户界面的快照。系统在应用切换器中显示生成的图像。当您的应用回到前台时,它还会临时显示图像。
您应用的 UI 不得包含任何敏感的用户信息,例如密码或信用卡号。如果您的界面包含此类信息,请在进入后台时将其从您的视图中删除。此外,消除隐藏应用程序内容的警报、临时界面和系统视图控制器。快照代表您的应用程序的界面,用户应该可以识别。当您的应用返回前台时,您可以根据需要恢复数据和视图。
见Technical Q&A QA1838: Preventing Sensitive Information From Appearing In The Task Switcher
除了隐藏/替换敏感信息之外,您可能还想告诉 iOS 7 不要通过ignoreSnapshotOnNextApplicationLaunch 拍摄屏幕快照,其文档中写道:
如果您觉得重新启动应用时快照无法正确反映应用的用户界面,您可以致电ignoreSnapshotOnNextApplicationLaunch 以防止拍摄快照图像。
话虽如此,屏幕快照似乎仍在拍摄,因此我提交了一份错误报告。但您应该进一步测试,看看使用此设置是否有帮助。
如果这是一个企业应用程序,您可能还想查看配置文件参考的Restrictions Payload 部分中列出的allowScreenShot 的适当设置。
这是一个实现我需要的实现。您可以提供自己的UIImageView,也可以使用委托协议模式来隐藏机密信息:
// SecureDelegate.h
#import <Foundation/Foundation.h>
@protocol SecureDelegate <NSObject>
- (void)hide:(id)object;
- (void)show:(id)object;
@end
然后我为我的应用委托提供了一个属性:
@property (weak, nonatomic) id<SecureDelegate> secureDelegate;
我的视图控制器设置它:
- (void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
delegate.secureDelegate = self;
}
视图控制器显然实现了该协议:
- (void)hide:(id)object
{
self.passwordLabel.alpha = 0.0;
}
- (void)show:(id)object
{
self.passwordLabel.alpha = 1.0;
}
最后,我的应用委托利用了这个协议和属性:
- (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:"];
}
注意,我使用的是applicationWillResignActive,而不是建议的applicationDidEnterBackground,因为正如其他人指出的那样,在应用程序运行时双击主页按钮时不会调用后者。
我希望我可以使用通知来处理所有这些,而不是委托协议模式,但在我有限的测试中,通知没有及时处理,但上述模式可以正常工作。