Представленный контроллер представления будет отклонен, если я переведу свое приложение в фоновый режим, а затем выйду на передний план в iOS

#ios #objective-c #appdelegate

#iOS #objective-c #appdelegate

Вопрос:

У меня было требование закрывать экран черным макетом, когда пользователь перемещает приложение в фоновый applicationDidEnterBackground, чтобы сохранить конфиденциальность некоторых конфиденциальных данных на экране. Итак, для этого я использовал функцию AppDelegate, чтобы представить черный цвет в фоновом режиме, а затем удалить его, отклонив его, когда дело доходит до переднего плана applicationDidEnterBackground. Код:

 #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
  

Теперь в моем приложении все работает нормально, но на одном экране я представляю ViewContollerB при нажатии кнопки с помощью: [self presentViewController:webview animated:YES completion:nil]; Приложение, как обычно, покрывается черным цветом при переходе на задний план, но когда я после этого перемещаю приложение на передний план, представленный ViewContollerB также отклоняется. Как предотвратить увольнение моего представленного ViewController после выхода из фона?

Комментарии:

1. Происходит ли это всякий раз, когда у вас в стеке более 1 контроллера просмотра (т. Е. Когда RootViewController представляет некоторые другие контроллеры просмотра)?

Ответ №1:

Создайте новый вызываемый UIViewController OverLayViewController и загрузите его в applicationDidEnterBackground метод

 - (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;
    }
}

  

В этом случае dismissViewContoller код не будет применяться к вашему webview.

Комментарии:

1. Извините, я сделал то же самое, но OverlayViewController не отключается при перемещении на передний план. Я хочу, чтобы OverlayViewController отключился, но мой WebView не должен отключаться при выходе на передний план

2. Приведенный выше код не должен отклонять ваш webview. Потому что это условие не позволит отклонить. if ([self.window.RootViewController isKindOfClass:[OverLayViewController class]]) {

3. Проблема сейчас в том, что когда я выхожу на передний план, OverLayViewController все еще показывает. Я не хочу этого

4. Код проверки из: github.com/prakashidesign/OverLayTest

5. if ([test isKindOfClass:[OverLayViewController class]]). Это условие if проверяет, является ли представленный контроллер представления OverLayViewController или нет.

Ответ №2:

Вы пытаетесь сделать следующее: rootviewcontroller A представляет пустой viewcontroller B. Ваше приложение переходит в фоновый режим, и вы представляете viewcontroller C оттуда. Теперь B закрывается, поскольку A представляет как B, так и C, а это недопустимо.

Вам нужно будет проверить, представляет ли ваш rootviewcontroller какие-либо viewcontrollers, и представляют ли они какие-либо другие рекурсивно. Вы можете проверить их, используя свойство presentedViewController в viewcontroller.

Лично я бы (в базовом классе viewcontroller, от которого наследуются все viewcontrollers) сохранил переменную, которая проверяет, видна ли эта (отслеживая viewDidAppear и viewDidDisappear ).). Если это тот, который виден, вы добавляете пустой вид сверху.

Ответьте в Swift, потому что мне нельзя доверять Objective-C без редактора:

 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
    }
}
  

Затем вам нужно отправить уведомление от AppDelegate , которое перехватывается в этом viewcontroller, а затем показать пустой вид сверху.

Комментарии:

1. не могли бы вы помочь мне с примером кода. Я попробовал [blankViewController dismissViewControllerAnimated: false completion: nil]; но все равно мой ViewControllerB отклоняется вместе с blankViewController

2. Ваш ViewControllerB отклоняется, когда вы представляете blankViewController (я думаю)

3. Можете ли вы проверить, какой из них когда удаляется? Вы можете использовать didMoveToParentViewController , чтобы проверить, удаляется ли ваш ViewControllerB при представлении blankviewcontroller или при отключении blankviewcontroller

4. спасибо за ответ, не могли бы вы сказать, где это проверить? делегирование внутри приложения?

5. Проверьте документацию: developer.apple.com/documentation/uikit/uiviewcontroller / …