Controlling the Screenshot in the iOS 7 Multitasking Switcher

Controlling the screenshot in the iOS 7 multitasking switcher

In Preparing Your UI to Run in the Background, Apple says:

Prepare Your UI for the App Snapshot


At some point after your app enters the background and your delegate method returns, UIKit takes a snapshot of your app’s current user interface. The system displays the resulting image in the app switcher. It also displays the image temporarily when bringing your app back to the foreground.

Your app’s UI must not contain any sensitive user information, such as passwords or credit card numbers. If your interface contains such information, remove it from your views when entering the background. Also, dismiss alerts, temporary interfaces, and system view controllers that obscure your app’s content. The snapshot represents your app’s interface and should be recognizable to users. When your app returns to the foreground, you can restore data and views as appropriate.

See Technical Q&A QA1838: Preventing Sensitive Information From Appearing In The Task Switcher

In addition to obscuring/replacing sensitive information, you might also want to tell iOS 7 to not take the screen snapshot via ignoreSnapshotOnNextApplicationLaunch, whose documentation says:

If you feel that the snapshot cannot correctly reflect your app’s user interface when your app is relaunched, you can call ignoreSnapshotOnNextApplicationLaunch to prevent that snapshot image from being taken.

Having said that, it appears that the screen snapshot is still taken and I have therefore filed a bug report. But you should test further and see if using this setting helps.

If this was an enterprise app, you might also want to look into the appropriate setting of allowScreenShot outlined in the Restrictions Payload section of the Configuration Profile Reference.


Here is an implementation that achieves what I needed. You can present your own UIImageView, or your can use a delegate-protocol pattern to obscure the confidential information:

//  SecureDelegate.h

#import <Foundation/Foundation.h>

@protocol SecureDelegate <NSObject>

- (void)hide:(id)object;
- (void)show:(id)object;

@end

I then gave my app delegate a property for that:

@property (weak, nonatomic) id<SecureDelegate> secureDelegate;

My view controller sets it:

- (void)viewDidLoad
{
[super viewDidLoad];

AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
delegate.secureDelegate = self;
}

The view controller obviously implements that protocol:

- (void)hide:(id)object
{
self.passwordLabel.alpha = 0.0;
}

- (void)show:(id)object
{
self.passwordLabel.alpha = 1.0;
}

And, finally, my app delegate avails itself of this protocol and property:

- (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:"];
}

Note, I'm using applicationWillResignActive rather than the advised applicationDidEnterBackground, because, as others have pointed out, the latter is not called when double tapping on the home button while the app is running.

I wish I could use notifications to handle all of this, rather than the delegate-protocol pattern, but in my limited testing, the notifications aren't handled in a timely-enough manner, but the above pattern works fine.

iOS 7+'s Goodbye Snapshot

It is possible to know when an app is going to resign active or be backgrounded. The UIApplicationDelegate protocol defines the method - (void)applicationWillResignActive:(UIApplication *)application which is called before an application is moved from active to inactive.

Knowing the timing of that method's invocation, you can do whatever you want before the app goes inactive. So, you could toss a view on top of the screen that contains whatever you want. This would then become the multitasking image, and the launch image.

Reference the following blog post for a more in depth analysis: http://blog.adambell.ca/post/73339778302/dynamic-ios-multitasking

iOS Multitask App Switcher Custom Image

From what I see, PayPal doesn't cover the viewport with a custom image immediately – when I double tap the Home button, it remains rendered normally until I do something else – but most probably on applicationDidEnterBackground:. After switching to Home screen or another application, the PayPal preview becomes covered.

On the other hand, my mobile banking application does that immediately when applicationWillResignActive: is triggered.

These are AFAIK the only two approaches you can achieve.

iOS 7 multitasking switcher: Navbar appears black

I ran into this as well. Since you don't have any content under the translucent navigation bar (and/or tab bar or tool bar), it can sometimes appear black in the app switcher. I was using a collection view that was constrained to the top and bottom layout guides and so there was nothing behind the tab bar and navigation bar. When the app is in the foreground it looks correct because there must be some default background color applied by Apple (maybe on the UIWindow) so you don't see through to the springboard. This background color seems to be gone (or black) when in the app switcher causing it to look like that.

The problem goes away on view controllers that are set to extend under top and/or bottom bars:


self.edgesForExtendedLayout = UIRectEdgeTop | UIRectEdgeBottom;

or in Interface Builder:

Sample Image

If that doesn't fit you needs or you still have other view controllers that don't extend under top and bottom bars you will still get the black bars in the app switcher. The way I solved it was to set the UIWindow background color in my appDelegate.

self.window.backgroundColor = [UIColor whiteColor];

How to block confidential information with Launch Screen or Image in Swift 4?

Currently your code is in Objective-c not swift , you can try this in swift

func applicationDidEnterBackground(_ application: UIApplication) {

let im = UIImageView()

im.tag = 12

im.frame = (self.window?.frame)!

im.image = UIImage.init(named: "add.png")

application.keyWindow?.subviews.last?.addSubview(im)
}

func applicationWillEnterForeground(_ application: UIApplication) {

if let sub = application.keyWindow?.subviews.last
{
for vv in sub.subviews
{
if(vv.tag == 12)
{
vv.removeFromSuperview()
}

}

}

}


Related Topics



Leave a reply



Submit