我一直在尝试寻找关于iOS 7中新的多任务切换器以及操作系统在应用程序进入休眠状态时所拍摄的截屏的信息。
有没有完全关闭这个功能或屏幕截图的方法?或者是否可以完全从切换器中隐藏该应用程序?该应用程序需要在后台运行,但我们不想显示任何来自该应用的截图。
截屏可能存在安全风险,考虑银行应用程序等情况,任何人双击设备的主按钮都可以查看您的卡号或账户汇总。
有了解的人可以提供帮助吗?谢谢。
我一直在尝试寻找关于iOS 7中新的多任务切换器以及操作系统在应用程序进入休眠状态时所拍摄的截屏的信息。
有没有完全关闭这个功能或屏幕截图的方法?或者是否可以完全从切换器中隐藏该应用程序?该应用程序需要在后台运行,但我们不想显示任何来自该应用的截图。
截屏可能存在安全风险,考虑银行应用程序等情况,任何人双击设备的主按钮都可以查看您的卡号或账户汇总。
有了解的人可以提供帮助吗?谢谢。
为应用快照准备您的UI
在您的应用程序进入后台并且委托方法返回后的某个时刻,UIKit会对您应用程序当前的用户界面进行快照。系统会在应用切换器中显示生成的图像。当把您的应用程序带回前台时,它也会暂时显示图像。
您的应用程序UI不能包含任何敏感用户信息,例如密码或信用卡号码。如果您的界面包含此类信息,请在进入后台时从视图中删除它。此外,当出现遮挡应用程序内容的警报、临时界面和系统视图控制器时,也要将其关闭。该快照代表您的应用程序界面,并且应该能被用户识别。当您的应用程序返回前台时,可以根据需要恢复数据和视图。
请参阅技术Q&A 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
然后,我为我的应用程序代理(app delegate)添加了一个属性:
@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
的文档是不正确的。正如我们所观察到的那样,实际上确实会拍摄快照,但在下一次启动时将不会使用它。 - Rob这是我用于我的应用程序的解决方案:
就像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,因为如果你双击home按钮,applicationDidEnterBackground不会被触发,而applicationWillResignActive则会被触发。虽然有人说它也可以在其他情况下触发,但我仍在测试中,看看它是否会出现问题,但目前还没有出现!;)
这里是移除图片视图的代码:
- (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];
}
}
in appDelegate just before implementation add line:
static const int kNVSBlurViewTag = 198490;//or wherever number you like
add this methods:
- (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;
}
make your appDelegate implementation be the as follows:
- (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 - 模糊视图将从窗口中移除。
如何使用:
Objective C
Add AppDelegate+NVSBlurAppScreen
.h and .m files to your project
in your -applicationWillResignActive: method add the following line:
[self nvs_blurPresentedView];
in your -applicationDidEnterBackground: method add the following line:
[self nvs_unblurPresentedView];
Swift
add AppDelegateExtention.swift file to your project
in your applicationWillResignActive function add the following line:
blurPresentedView()
in your applicationDidBecomeActive function add the following line:
unblurPresentedView()
如果只在applicationWillResignActive
函数中使用[self.window addSubview:imageView];
,这个imageView不会覆盖UIAlertView、UIActionSheet或MFMailComposeViewController...
最好的解决办法是
- (void)applicationWillResignActive:(UIApplication *)application
{
UIWindow *mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
[mainWindow addSubview:imageView];
}
您可以使用激活器来配置双击主页按钮以启动多任务处理,并禁用默认的双击主页按钮和启动多任务处理窗口。此方法可用于将屏幕截图更改为应用程序的默认图像。这适用于具有默认密码保护功能的应用程序。
虽然我的解决方案非常不可靠,但我会提供自己的“答案”。有时我会得到一个黑屏截图,有时是XIB,有时是应用程序本身的截图。这取决于设备和/或是否在模拟器中运行。
请注意,我无法为此解决方案提供任何代码,因为其中包含了很多特定于应用程序的细节。但这应该可以解释我的解决方案的基本要点。
在AppDelegate.m文件的applicationWillResignActive下,我检查我们是否正在运行iOS7,如果是,我加载一个新视图,其中心是空的,并带有应用程序标志。一旦调用了applicationDidBecomeActive,我重新启动我的旧视图,这将被重置 - 但对于我正在开发的应用程序类型来说,这是有效的。
Xamarin.iOS
参考自https://dev59.com/02Mk5IYBdhLWcg3wyw7H#20040270
我不仅想显示一种颜色,而是要显示我的启动屏幕。
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();
}