简体   繁体   中英

Presented view controller gets dismissed if i move my application to background and then come to foreground in iOS

I had a requirement to cover the screen with black layout when the user moves the application to the background applicationDidEnterBackground in order to maintain the privacy of some sensitive datas on the screen. So for this i made use of AppDelegate function to present with a black color in background and then remove that by dismissing it when comes to foreground applicationDidEnterBackground . The code is:

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    UIViewController *blankViewController = [UIViewController new];
    blankViewController.view.backgroundColor = [UIColor blackColor];
    [self.window makeKeyAndVisible];
    [self.window.rootViewController presentViewController:blankViewController animated:NO completion:NULL];
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    [self.window.rootViewController dismissViewControllerAnimated:false completion:nil];
}

@end

Now in my application everything is working fine but in one screen i am presenting a ViewContollerB on a button click by using : [self presentViewController:webview animated:YES completion:nil]; The application as usually gets covered with black color when moving to background but when i take the application to foreground after this, then the presented ViewContollerB also gets dismissed . How to prevent my presented ViewController to get dismissed once coming from background?

You are trying to do the following: rootviewcontroller A presents a blank viewcontroller B. Your app goes into background, and you present viewcontroller C from there. Now B closes as A is presenting both B and C, and that is not allowed.

You will need to check if your rootviewcontroller is presenting any viewcontrollers, and if those are presenting any others recursively. You can check for those by using the property presentedViewController on a viewcontroller.

Personally, I would (in a base viewcontroller class that all viewcontrollers inherit from) keep a variable that checks if this one is visible (by keeping track of viewDidAppear and viewDidDisappear ). If this is the one that is visible, you add a blank view on top.

Answer in Swift because I can't be trusted with Objective-C without an editor:

class BaseViewController: UIViewController {
    var appeared = false

    func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated: animated)
        appeared = true
    }

    func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated: animated)
        appeared = false
    }
}

Then you need to fire a notification from the AppDelegate that is caught in this viewcontroller, and then show a blank view on top.

Create a new 'UIViewController' called OverLayViewController and load it in applicationDidEnterBackground method

- (void)applicationDidEnterBackground:(UIApplication *)application {
    OverLayViewController *blankViewController = [OverLayViewController new];
    blankViewController.view.backgroundColor = [UIColor blackColor];
    [self.window makeKeyAndVisible];
    
    UIViewController *rvc = self.window.rootViewController;
    UIViewController *pvc = rvc.presentedViewController;  // you may need to loop through presentedViewControllers if you have more than one
    if(pvc != nil) {
        [pvc presentViewController: blankViewController animated: NO completion:nil];
    }
    else{
        [self.window.rootViewController presentViewController: blankViewController animated: NO completion:nil];
    }
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    UIViewController *test = [self topViewController];
    if ([test isKindOfClass:[OverLayViewController class]]) {
           [test dismissViewControllerAnimated:false completion:nil];
    }
}


- (UIViewController*)topViewController {
    return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

-(UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

In this case, dismissViewContoller code wont apply for your webview.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM