在iOS 7多任务切换器中控制屏幕截图


98

我一直在尝试寻找有关iOS 7中新的多任务切换器的信息,尤其是当应用程序进入休眠状态时操作系统所截取的屏幕截图。

在此处输入图片说明

有什么方法可以完全关闭此功能或屏幕截图吗?还是可以从切换台中完全隐藏应用程序?该应用程序需要在后台运行,但是我们不想显示该应用程序的任何屏幕截图。

屏幕截图可能会带来安全风险,请仔细考虑银行应用程序,双击该设备上的“主页”按钮的任何人都可以使用您的卡号或帐户摘要。

任何对此有见识的人吗?谢谢。


1
我当前的解决方案是在应用进入休眠状态后,在应用中加载带有应用徽标的空白视图,并在应用返回时将其删除,但是该解决方案难以管理,而且看起来像是骇客,而不是优雅的解决方案。此外,此解决方案有时会因设备等原因而失败。因此,它并不是真正可用的解决方案。
Tommie 2013年

Answers:


101

准备UI在后台运行时,Apple说:

为应用程序快照准备UI

在您的应用程序进入后台并且您的委托方法返回之后的某个时刻,UIKit会为您的应用程序当前用户界面拍摄快照。系统在应用程序切换器中显示生成的图像。当您的应用回到前台时,它还会临时显示图像。

您应用的用户界面不得包含任何敏感的用户信息,例如密码或信用卡号。如果您的界面包含此类信息,请在进入背景时从视图中将其删除。另外,请关闭使您的应用内容模糊的警报,临时界面和系统视图控制器。快照代表了您应用的界面,应该可以被用户识别。当您的应用返回到前台时,您可以适当地还原数据和视图。

请参阅技术问答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,因为,正如其他人指出的那样,在应用程序运行时双击主屏幕按钮时,不会调用后者。

我希望我可以使用通知来处理所有这些,而不是使用委托协议模式,但是在我有限的测试中,通知没有以足够及时的方式进行处理,但是上述模式可以正常工作。


6
请注意,正如此处stackoverflow.com/questions/18937313/…所述,模拟器中的行为并不总是与设备上的行为相同!
Michael Forrest

5
对于它的价值时,ignoreSnapshotOnNextApplicationLaunch如果没有状态恢复过程调用,描述被忽略的方法在这里
Charles A.

3
您无需在applicationWillResignActive中执行此操作,因为直到applicationDidEnterBackground才截取屏幕截图。双击“主页”按钮时,不会拍摄任何屏幕截图。您所看到的屏幕是实时的。在屏幕上添加动画以进行验证,例如循环显示背景色。如果您随后选择另一个应用程序,则会在获取实际屏幕截图之前调用applicationDidEnterBackground。
2014年

3
顺便说一句,我从一位苹果工程师那里得知该文档ignoreSnapshotOnNextApplicationLaunch是不正确的,正如我们所有人所观察到的,快照实际上是拍摄的,但是在下一次发布时将不再使用。
罗布2014年

2
ignoreSnapshotOnNextApplicationLaunch似乎听起来很像:防止在应用程序启动期间显示屏幕截图。它不会影响多任务UI屏幕截图,也不会影响应用程序正在恢复而不是启动。
Glenn Maynard

32

这是我为应用程序使用的解决方案:

正如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;
    }
}

希望这可以帮助!

旁注:我在模拟器和真实设备上都对此进行了测试:它不会在模拟器上显示,但会在真实设备上显示!


2
有一个缺点:在用户拉下通知停靠栏时,会调用applicationWillResignActive。因此,当您期望看到应用程序内容时,您可以从顶部向下滑动手指来查看该图像。
Kirill Gamazkov 2014年

4
最好在applicationWillResignActive上模糊敏感信息,并在
aplicationDidEnterBackground

这行得通,但是在部署到使用xCode6构建的iOS7时,存在一个轮换错误:stackoverflow.com/questions/26147068/…–
Alex Stone

如果我编写了您在applicationWillResignActive中提到的代码,那么当我将应用程序恢复为前台状态时会看到什么?我会看到“ Portrait(768x1024).png”图像还是实际屏幕?
NSPratik

2
@Pratik:您将看到该图像,除非您在applicationDidBecomeActive方法中再次将其删除(请参见上文)。
劳拉

14

这种快速简便的方法将在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];
    }
}

4

我使用以下解决方案:当应用程序要辞职时,我将appWindow快照作为View并对其添加模糊效果。然后我将此视图添加到应用程序窗口

这该怎么做:

  1. 在appDelegate中,在实现之前添加行:

    static const int kNVSBlurViewTag = 198490;//or wherever number you like
  2. 添加此方法:

    - (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;
        }
  3. 使您的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];
    }

我在SwiftObjective C中创建了Example项目。这两个项目都在以下方面进行以下操作:

-application:didResignActive-创建快照,将其模糊并添加到应用程序窗口

-application:willBecomeActive模糊视图正在从窗口中删除。

如何使用:

客体C

  1. AppDelegate+NVSBlurAppScreen.h和.m文件添加到您的项目

  2. 在您的-applicationWillResignActive:方法中,添加以下行:

    [self nvs_blurPresentedView];
  3. 在您的-applicationDidEnterBackground:方法中,添加以下行:

    [self nvs_unblurPresentedView];

迅速

  1. 将AppDelegateExtention.swift文件添加到您的项目

  2. 在applicationWillResignActive函数中添加以下行:

    blurPresentedView()
  3. 在您的applicationDidBecomeActive函数中添加以下行:

    unblurPresentedView()

2

如果仅[self.window addSubview:imageView];applicationWillResignActive函数中使用,则此imageView不会覆盖UIAlertView,UIActionSheet或MFMailComposeViewController ...

最好的解决方案是

- (void)applicationWillResignActive:(UIApplication *)application
{
    UIWindow *mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
    [mainWindow addSubview:imageView];
}

如果您在网络视图中以全屏模式播放视频,这是一个很好的解决方案!
Tommie

优秀的!。即使在进入多任务切换台之前打开键盘,它也能正常工作!谢谢
Prabhu.Somasundaram

0

提供我自己的解决方案作为“答案”,尽管这种解决方案非常不可靠。有时我会在屏幕上看到黑屏,有时是XIB,有时是应用程序本身的屏幕截图。取决于设备和/或是否在模拟器中运行。

请注意,由于其中包含许多特定于应用程序的详细信息,因此我无法为此解决方案提供任何代码。但这应该可以解释我的解决方案的基本要点。

在applicationWillResignActive下的AppDelegate.m中,我检查是否正在运行iOS7,如果要加载,请加载一个中间为app-logo的新视图。调用applicationDidBecomeActive之后,我会重新启动我的旧视图,该视图将被重置-但这适用于我正在开发的应用程序类型。


1
如果您看到Camera应用程序的功能-进入背景时,它将图像转换为模糊的图像(您可以看到转换过程
缩小

@Petesh是的,这是一个不错的实现,但是问题是他们是如何做到的。我担心会使用私有API。
罗布2013年

@Tommie您说“取决于设备和/或是否在模拟器中运行它”。对我来说,它似乎可以在设备上运行(尽管我还没有进行详尽的测试),但是在模拟器上却没有。您是否发现它在设备上不起作用?
罗布2013年

0

您可以使用激活器来配置双击主页按钮以启动多任务,并禁用默认双击主页按钮和启动多任务窗口。此方法可用于将屏幕截图更改为应用程序的默认图像。这适用于具有默认密码保护功能的应用程序。


-2

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();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.