我一直在尝试寻找有关iOS 7中新的多任务切换器的信息,尤其是当应用程序进入休眠状态时操作系统所截取的屏幕截图。
有什么方法可以完全关闭此功能或屏幕截图吗?还是可以从切换台中完全隐藏应用程序?该应用程序需要在后台运行,但是我们不想显示该应用程序的任何屏幕截图。
屏幕截图可能会带来安全风险,请仔细考虑银行应用程序,双击该设备上的“主页”按钮的任何人都可以使用您的卡号或帐户摘要。
任何对此有见识的人吗?谢谢。
我一直在尝试寻找有关iOS 7中新的多任务切换器的信息,尤其是当应用程序进入休眠状态时操作系统所截取的屏幕截图。
有什么方法可以完全关闭此功能或屏幕截图吗?还是可以从切换台中完全隐藏应用程序?该应用程序需要在后台运行,但是我们不想显示该应用程序的任何屏幕截图。
屏幕截图可能会带来安全风险,请仔细考虑银行应用程序,双击该设备上的“主页”按钮的任何人都可以使用您的卡号或帐户摘要。
任何对此有见识的人吗?谢谢。
Answers:
在准备UI在后台运行时,Apple说:
为应用程序快照准备UI
在您的应用程序进入后台并且您的委托方法返回之后的某个时刻,UIKit会为您的应用程序当前用户界面拍摄快照。系统在应用程序切换器中显示生成的图像。当您的应用回到前台时,它还会临时显示图像。
您应用的用户界面不得包含任何敏感的用户信息,例如密码或信用卡号。如果您的界面包含此类信息,请在进入背景时从视图中将其删除。另外,请关闭使您的应用内容模糊的警报,临时界面和系统视图控制器。快照代表了您应用的界面,应该可以被用户识别。当您的应用返回到前台时,您可以适当地还原数据和视图。
除了遮盖/替换敏感信息之外,您还可能希望通过告诉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
,因为,正如其他人指出的那样,在应用程序运行时双击主屏幕按钮时,不会调用后者。
我希望我可以使用通知来处理所有这些,而不是使用委托协议模式,但是在我有限的测试中,通知没有以足够及时的方式进行处理,但是上述模式可以正常工作。
ignoreSnapshotOnNextApplicationLaunch
如果没有状态恢复过程调用,描述被忽略的方法在这里。
ignoreSnapshotOnNextApplicationLaunch
是不正确的,正如我们所有人所观察到的,快照实际上是拍摄的,但是在下一次发布时将不再使用。
这是我为应用程序使用的解决方案:
正如Tommy所说:您可以使用applicationWillResignActive。我所做的是用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或更高版本的应用程序切换器中的应用程序图标上方产生黑色快照。
首先,获取应用程序的关键窗口(通常在application:didFinishLaunchingWithOptions中的AppDelegate.m中设置),并在您的应用程序将要移入后台时将其隐藏:
- (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快照作为View并对其添加模糊效果。然后我将此视图添加到应用程序窗口
这该怎么做:
在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中创建了Example项目。这两个项目都在以下方面进行以下操作:
-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();
}