我一直在尝试查找有关 iOS 7 中新的多任务切换器的一些信息,尤其是当应用程序进入休眠状态时操作系统拍摄的屏幕截图。
有没有办法完全关闭这个功能或截图?或者我可以从切换器中完全隐藏应用程序吗?该应用程序需要在后台运行,但我们不想显示该应用程序的任何屏幕截图。
屏幕截图可能存在安全风险,请考虑银行应用程序的思路,双击设备上的主页按钮的任何人都可以使用您的卡号或帐户摘要。
任何对此有任何见解的人?谢谢。
在准备你的 UI 以在后台运行时,Apple 说:
为应用快照准备 UI
在您的应用程序进入后台并且您的委托方法返回后的某个时间点,UIKit 会拍摄您的应用程序当前用户界面的快照。系统在应用切换器中显示生成的图像。当您的应用程序回到前台时,它还会临时显示图像。
您应用的 UI 不得包含任何敏感的用户信息,例如密码或信用卡号。如果您的界面包含此类信息,请在进入后台时将其从您的视图中删除。此外,消除会掩盖应用内容的警报、临时界面和系统视图控制器。快照代表您的应用程序的界面,用户应该可以识别。当您的应用返回前台时,您可以根据需要恢复数据和视图。
请参阅技术问答 QA1838:防止敏感信息出现在任务切换器中
除了隐藏/替换敏感信息之外,您可能还想告诉 iOS 7 不要通过 获取屏幕快照ignoreSnapshotOnNextApplicationLaunch
,其文档说:
如果您觉得重新启动应用时快照无法正确反映应用的用户界面,您可以调用
ignoreSnapshotOnNextApplicationLaunch
以阻止拍摄该快照图像。
话虽如此,屏幕快照似乎仍在拍摄,因此我提交了一份错误报告。但是您应该进一步测试,看看使用此设置是否有帮助。
如果这是一个企业应用程序,您可能还需要查看配置文件参考的限制有效负载部分中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
,因为正如其他人指出的那样,在应用程序运行时双击主页按钮时不会调用后者。
我希望我可以使用通知来处理所有这些,而不是委托协议模式,但是在我有限的测试中,通知没有以足够及时的方式处理,但上述模式工作正常。
这是我为我的应用程序使用的解决方案:
正如汤米所说:您可以使用应用程序WillResignActive。我所做的是用我的 SplashImage 制作一个 UIImageView 并将其作为子视图添加到我的主窗口 -
(void)applicationWillResignActive:(UIApplication *)application
{
imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
[imageView setImage:[UIImage imageNamed:@"Portrait(768x1024).png"]];
[self.window addSubview:imageView];
}
我使用此方法而不是 applicationDidEnterBackground,因为如果您双击主页按钮,将不会触发 applicationDidEnterBackground,而会触发 applicationWillResignActive。我听说人们说虽然它也可以在其他情况下触发,所以我仍在测试它是否有问题,但到目前为止还没有!;)
这里要删除imageview:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(imageView != nil) {
[imageView removeFromSuperview];
imageView = nil;
}
}
希望这可以帮助!
旁注:我在模拟器和真实设备上都进行了测试:它不会在模拟器上显示,但在真实设备上会显示!
这种快速简便的方法将在 iOS7 或更高版本的应用切换器中的应用图标上方生成黑色快照。
首先,获取应用的关键窗口(通常在 AppDelegate.m 中的 application:didFinishLaunchingWithOptions 中设置),并在应用即将进入后台时将其隐藏:
- (void)applicationWillResignActive:(UIApplication *)application
{
if(isIOS7Or8)
{
self.window.hidden = YES;
}
}
然后,当您的应用再次激活时,取消隐藏您的应用的关键窗口:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(isIOS7Or8)
{
self.window.hidden = NO;
}
}
此时,检查应用切换器并确认您在应用图标上方看到黑色快照。我注意到,如果您在将应用程序移至后台后立即启动应用程序切换器,则可能会有约 5 秒的延迟,您会看到应用程序的快照(您要隐藏的快照!),之后它转换为全黑快照。我不确定延迟是怎么回事;如果有人有任何建议,请加入。
如果您想在切换器中使用黑色以外的颜色,您可以通过添加具有您想要的任何背景颜色的子视图来执行此类操作:
- (void)applicationWillResignActive:(UIApplication *)application
{
if(isIOS7Or8)
{
UIView *colorView = [[[UIView alloc] initWithFrame:self.window.frame] autorelease];
colorView.tag = 9999;
colorView.backgroundColor = [UIColor purpleColor];
[self.window addSubview:colorView];
[self.window bringSubviewToFront:colorView];
}
}
然后,当您的应用再次激活时,删除此颜色子视图:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(isIOS7Or8)
{
UIView *colorView = [self.window viewWithTag:9999];
[colorView removeFromSuperview];
}
}
我使用了以下解决方案:当应用程序要辞职时,我将 appWindow 快照作为视图并为其添加模糊。然后我将此视图添加到应用程序窗口
这该怎么做:
在 appDelegate 实现之前添加一行:
static const int kNVSBlurViewTag = 198490;//or wherever number you like
添加此方法:
- (void)nvs_blurPresentedView
{
if ([self.window viewWithTag:kNVSBlurViewTag]){
return;
}
[self.window addSubview:[self p_blurView]];
}
- (void)nvs_unblurPresentedView
{
[[self.window viewWithTag:kNVSBlurViewTag] removeFromSuperview];
}
#pragma mark - Private
- (UIView *)p_blurView
{
UIView *snapshot = [self.window snapshotViewAfterScreenUpdates:NO];
UIView *blurView = nil;
if ([UIVisualEffectView class]){
UIVisualEffectView *aView = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
blurView = aView;
blurView.frame = snapshot.bounds;
[snapshot addSubview:aView];
}
else {
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:snapshot.bounds];
toolBar.barStyle = UIBarStyleBlackTranslucent;
[snapshot addSubview:toolBar];
}
snapshot.tag = kNVSBlurViewTag;
return snapshot;
}
使您的 appDelegate 实现如下:
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
//...
//your code
//...
[self nvs_blurPresentedView];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
//...
//your code
//...
[self nvs_unblurPresentedView];
}
我在Swift和Objective C中创建了示例项目。这两个项目都采取了以下行动:
-application:didResignActive - 创建、模糊并添加到应用程序窗口的快照
-application:willBecomeActive模糊视图正在从窗口中删除。
如何使用:
目标 C
将AppDelegate+NVSBlurAppScreen
.h 和 .m 文件添加到您的项目中
在您的 -applicationWillResignActive: 方法中添加以下行:
[self nvs_blurPresentedView];
在您的 -applicationDidEnterBackground: 方法中添加以下行:
[self nvs_unblurPresentedView];
迅速
将 AppDelegateExtention.swift 文件添加到您的项目中
在您的 applicationWillResignActive 函数中添加以下行:
blurPresentedView()
在您的 applicationDidBecomeActive 函数中添加以下行:
unblurPresentedView()
如果仅[self.window addSubview:imageView];
在applicationWillResignActive
函数中使用,此 imageView 不会覆盖 UIAlertView、UIActionSheet 或 MFMailComposeViewController...
最好的解决方案是
- (void)applicationWillResignActive:(UIApplication *)application
{
UIWindow *mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
[mainWindow addSubview:imageView];
}
提供我自己的解决方案作为“答案”,尽管这个解决方案非常不可靠。有时我得到一个黑屏作为屏幕截图,有时是 XIB,有时是来自应用程序本身的屏幕截图。取决于设备和/或如果我在模拟器中运行它。
请注意,我无法为此解决方案提供任何代码,因为其中包含许多特定于应用程序的详细信息。但这应该解释我的解决方案的基本要点。
在 applicationWillResignActive 下的 AppDelegate.m 中,我检查我们是否正在运行 iOS7,如果我们运行,我会加载一个新视图,该视图为空,中间有 app-logo。一旦 applicationDidBecomeActive 被调用,我就会重新启动我的旧视图,这将被重置——但这适用于我正在开发的应用程序类型。
您可以使用激活器配置双击主页按钮以启动多任务处理并禁用默认双击主页按钮和启动多任务窗口。此方法可用于将屏幕截图更改为应用程序的默认图像。这适用于具有默认密码保护功能的应用程序。
Xamarin.iOS
改编自https://stackoverflow.com/a/20040270/7561
而不是只显示一种颜色,我想显示我的启动屏幕。
public override void DidEnterBackground(UIApplication application)
{
//to add the background image in place of 'active' image
var backgroundImage = new UIImageView();
backgroundImage.Tag = 1234;
backgroundImage.Image = UIImage.FromBundle("Background");
backgroundImage.Frame = this.window.Frame;
this.window.AddSubview(backgroundImage);
this.window.BringSubviewToFront(backgroundImage);
}
public override void WillEnterForeground(UIApplication application)
{
//remove 'background' image
var backgroundView = this.window.ViewWithTag(1234);
if(null != backgroundView)
backgroundView.RemoveFromSuperview();
}