Неправильная иерархия представлений: не рекомендуется представлять контроллеры представлений на отдельных контроллерах представлений

#ios #view #hierarchy #iad #rootview

#iOS #Вид #иерархия #iad #rootview

Вопрос:

Я получаю предупреждение, связанное с моим использованием GKTurnBasedMatchmakerViewController и BannerViewController для iAd. Это предупреждение:

 Presenting view controllers on detached view controllers is discouraged <RootViewController: 0x14cd143c0>
  

Что не так с показанной ниже последовательностью кода, которая вызывает это предупреждение?

В AppDelegate.h

 @interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow            *window;
RootViewController  *viewController;
}
  

В AppDelegate.m

 - (void) applicationDidFinishLaunching:(UIApplication*)application {

    viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];

    [window setRootViewController:viewController];
    [window addSubview: viewController.view];
}
  

Затем, когда пользователь нажимает кнопку воспроизведения на моем главном экране, я сначала открываю контроллер представления game center следующим образом (обратите внимание, что во 2-й строке задается параметр presentingViewController, равный RootViewController, который был настроен в AppDelegate):

 AppDelegate * theAppDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
self.presentingViewController = theAppDelegate.viewController;
GKTurnBasedMatchmakerViewController *mmvc = [[GKTurnBasedMatchmakerViewController alloc] initWithMatchRequest:request];
[presentingViewController presentViewController: mmvc animated: YES completion:nil];
  

После выполнения приведенного выше кода загружается новая сцена. Эта сцена описана в моем GameSelectionLayer.h следующим образом:

 @interface GameSelectionLayer : CCLayer <InAppStoreControlLayerDelegate> {
    ...
    RootViewController *viewController;
    AppDelegate *app;
    BannerViewController *bannerViewController;
} 
  

Затем в моем GameSelectionLayer.mm я загружаю bannerViewController onEnter следующим образом:

 -(void)onEnter {
    [super onEnter];

    app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    viewController = [(AppDelegate *)[[UIApplication sharedApplication] delegate] viewController];

    bannerViewController = [[BannerViewController alloc] initWithContentViewController:viewController];
    app.window.rootViewController = bannerViewController;
}
  

Я получаю вышеупомянутое предупреждение при выполнении приведенного выше кода. Пожалуйста, дайте мне знать, что, по вашему мнению, я могу делать неправильно, что вызывает это предупреждение.

Ответ №1:

Проблема в том, что вы заменяете иерархию представлений контроллера представления, в котором представлен другой контроллер представления. Предупреждение «отключено» появляется при попытке представить контроллер представления из контроллера представления, который не подключен к окну или не имеет дочернего контроллера представления, подключенного к окну.

Здесь я рекомендую два подхода. Либо отключите все контроллеры представлений перед заменой корневого контроллера представления, либо, что лучше из двух вариантов, используйте другое окно с собственной иерархией контроллеров корневого представления.

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

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

1. Итак, контроллеры представлений для меня немного загадочны. Я думаю, вы говорите, что моя ошибка в методе «onEnter». Как бы вы предложили реализовать свой 2-й вариант? Что вы подразумеваете под использованием другого окна с собственной иерархией корневых представлений?

2. Это означает создание нового UIWindow объекта, сохранение его (это важно!), присвоение rootViewController свойства контроллеру представления, который вы хотите отобразить, и вызов makeKeyAndVisible в новом окне.

3. В рамках метода «onEnter», показанного в моем вопросе, я создал новое UIWindow и сохранил его. Я установил свойство RootViewController для контроллера представления, который я хочу отобразить (а именно bannerViewController), и я сделал новое окно Keyandviewable. Это приводит к сбою, потому что я делаю RootViewController дочерним элементом bannerViewController. Другими словами, я удалил последнюю строку «onEnter» и добавил следующие строки: window = [[UIWindow alloc] initWithFrame: [[Границы главного экрана UIScreen]]; [окно setRootViewController: bannerViewController]; [окно makeKeyAndVisible];

4. Вы должны добавить его как дочерний элемент. У вас должно быть это автономно в своем собственном окне.

5. Добавить что в качестве дочернего элемента чего? Опять же, я удалил последнюю строку «onEnter» и добавил следующие строки: window = [[UIWindow alloc] initWithFrame: [[Границы главного экрана UIScreen]]; [окно setRootViewController: bannerViewController]; [окно makeKeyAndVisible];