Попередження: - Представлення контролерів подання на від'єднаних контролерах перегляду не рекомендується


180

У своєму додатку я використовую контролер навігації. Пізніше в деякому представленні я використовую presentViewControllerдля відображення масштабованого зображення. Крім того, я не використовую дошку розкадрування або ручку.

Я отримую цю помилку лише в iOS 7. Це добре працює в iOS 6 і новіших версіях:

Представлення контролерів подання на відокремлених контролерах перегляду не рекомендується


Я ще не з'ясував. Але в моєму додатку я не призначаю жодного виду контролера window.rootviewcontroller. я додаю перегляд до вікна. Можливо, це для мене причина. але не впевнений ...
Гаган Джоші

@GaganJoshi Причина, яку ви згадали вище, може не бути причиною. Навіть я стикаюся з тим же питанням. І в нашому проекті я призначаю контролер перегляду window.rootviewcontroller.
Раджеш

1
Я думаю, що інші коментарі правильно пов’язують це з чимось про rootViewController та підключення до вікна. Я не зовсім зрозумів це, але мені вдалося вирішити проблему, представивши контролер безпосередньо на rootViewController замість навігаційного контролера чи одного з його дітей.
Багаті води

Відповіді:


207

Щоб уникнути отримання попередження в навігаційній навігації, ви можете безпосередньо використовувати:

[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];

And then in your modal view controller, when everything is finished, you can just call :

[self dismissViewControllerAnimated:YES completion:nil];


I am presenting image picker with this line code "[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];" But unable dismiss poicker view with this line "[self dismissViewControllerAnimated:YES completion:nil];" Any alternate option for dismisscontroller
kb920

@keyurbhalodiya You need to call the dismissViewController method from the modalView to make it work. So if you displayed a view named viewB from a viewA with [viewA.window.rootViewController presentViewController:viewB], in viewB you need to add a button for example, associated to a custom action calling [self dismissViewControllerAnimated]. Is it clearer ?
cdescours

11
Not presenting viewcontroller in iOS 8.
Rajesh Maurya

1
for iOS 8: [self.view.window.rootViewController.navigationController
Fede Cugliandolo

31
використовуючи self.navigationControllerзробив це для мене.
Брендон Захарі

62

Причиною цього попередження є те, що я представляв контролер подання невеликого перегляду, який не є повнорозмірним поданням. Наведене нижче - зображення мого проекту. де натисніть на чотири варіанти вище. Користувач переходить до перегляду дочірнього контролера (він працює як tabViewcontroller). Але контролер дитячого контролю містить перегляд невеликих розмірів. Тож якщо ми подаємо вигляд контролера від догляду за дітьми, це попереджає.

перегляд деталей майстра

І щоб цього уникнути, ви можете представити погляд на батьківського контролера дитячого контролю

  [self.parentViewController presentViewController:viewController animated:YES completion:nil];

1
[self.view.window.rootViewController.navigationController pushViewController: YOUR_VIEW_CONTROLER анімований: ТАК];
Fede Cugliandolo

1
"представляв контролер подання для невеликого перегляду, який не є повнорозмірним поданням." ... ТОЧНО Хороша робота.
Fattie

61

Зачекайте viewDidAppear():

Ця помилка також може виникнути, якщо ви намагаєтеся представити контролер перегляду до того, як перегляд фактично з'явився, наприклад, представлення подання у viewWillAppear()або раніше. Спробуйте представити інший вигляд після нього viewDidAppear()або всередині нього.


9
Іншими словами, люди не представляйте ніяких контролерів перегляду viewDidLoad(), люди! Я так багато разів робив цю помилку ...
T Бланк

Завдяки цьому допомогло. У мене був код у viewDidLoad, де він намагався відобразити діалог у кінці.
ArdenDev

Я отримую цю помилку під час запуску одиничних / інтеграційних тестів, де я не тестую анімацію.
mixly87

21

У моєму випадку я sampleViewControllerвидаю подання як підвід, а потім намагається представити перехід з виду sampleViewController(тут selfзамість UIViewControllerекземпляра):

[self.view addSubview:sampleViewController.view];

Правильний шлях повинен бути нижче:

// make sure the vc has been added as a child view controller as well
[self addChildViewController:sampleViewController];
[self.view addSubview:sampleViewController.view];
[sampleViewController didMoveToParentViewController:self];

До речі, це також працює у випадку, коли подання утворює комірку tableview, вам просто потрібно переконатися, що контролер tableview також доданий як дочірній контролер.


Крім того, виклик didMoveToParentViewController. Просимо перевірити додавання та видалення ChildViewController: gist.github.com/tomohisa/2897676
Jakehao

@jianzong, я пам'ятаю, немає необхідності робити останній крок. Будь-який спосіб, дозвольте додати, THX для пропозиції. :)
Кюли

Так, це буде працювати без останнього кроку. Я думаю, що мета цього - повідомити parentViewController, щоб він закликав деякі методи зробити щось. :)
Jakehao

2
це працює для мене, я використовую один вигляд контролерів в іншому контролері - (перегляд контейнера програмно), я не додав [self addChildViewController:sampleViewController];, тепер я додав це, дякую
anjnkmr

16

Я думаю, що проблема полягає в тому, що у вас немає належної ієрархії контролерів перегляду. Встановіть кореневий контролер програми, а потім показуйте нові представлення, натискаючи або представляючи нові контролери перегляду на них. Нехай кожен контролер перегляду керує своїми поглядами. Лише контролери перегляду контейнерів, як-от табло перегляду контролера табл, повинні коли-небудь додавати інші подання контролерів перегляду до власних представлень. Прочитайте посібник з програмування контролерів перегляду, щоб дізнатися більше про правильне використання контролерів перегляду. https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/


14

Швидкий 3

Для тих, хто спотикається на цьому, ось швидка відповідь.

self.parent?.present(viewController, animated: true, completion: nil)

9

У мене майже однакова проблема. Причиною було те, що я намагався представити "якийсь" контролер на іншому, і після того, як анімація була завершена, я встановлював представлений контролер як root. Після цієї операції всі подані контролери приводять мене до попередження: " Представлення контролерів подання на контролерах відокремленого виду не рекомендується ". І я вирішую це попередження просто налаштовуючи "якийсь" контролер як корінь без будь-якої презентації на початку.

Видалено:

[[self rootController] presentViewController:controller animated:YES completion:^{

       [self window].rootViewController = controller;

       [[self window] makeKeyAndVisible];}];

Просто зробіть як root без будь-якої презентації:

 [[self window] setRootViewController:controller];

1
Це була саме моя проблема. Спробував представити його за допомогою UIModalTransitionStyleCrossDissolve, а потім зробити це rootViewController. Після цього всі інші презентації закінчувались поданням попереджувального повідомлення. Просто встановлення його як rootViewcontroller без анімації зробило свою справу. Дякую!
Бернардо Олівейра

7

Одним з рішень цього є те, якщо у вас є childviewcontroller, тож ви просто подаєте viewviewcontroller на його батьківському по даному

[self.parentViewController presentViewController:viewController animated:YES completion:nil];

А для звільнення використовуйте той же контролер відхилення.

[self dismissViewControllerAnimated:YES completion:nil];

Це ідеальне рішення працює для мене.



5

Спробуйте цей код

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:<your ViewController object>];

[self.view.window.rootViewController presentViewController:navigationController animated:YES completion:nil];

4

Спробуйте представити, TabBarControllerчи це TabBarControllerбазований додаток.

[self.tabBarController presentViewController:viewController animated:YES completion:nil];

Причина може бути self- це дитина, TabBarControllerі ви намагаєтесь представити її з ChildViewController.


4

Так, я також зіткнувся з тим же попереджувальним повідомленням під час відображення контролера Alert, який був в іншому вікні. Пізніше я цього уникнув, подавши контролер попередження від батьківського контролера подання, як показано нижче:

[self.parentViewController presentViewController:alertController animated:YES completion:nil];

3

вам потрібно додати контролер перегляду, який буде представляти новий контролер як дочірнє джерело контролера подання.

Скажімо, у вас є вашMainViewController, потім ви додаєте новий контролер під назвою controllerA, а потім ви хочете представити новий контролер під назвою controllerB від controllerA

ви повинні написати щось подібне:

[self addChildViewController:controllerA]; //self is yourMainViewController
[self.view addsubView:controllerA.view]; 

а в контролеріA ви можете представити новий контролер без попереджень

[self presentViewController:controllerB animated:YES completion:nil]; //self is controllerA

3

У Swift 4.1 та Xcode 9.4.1

Рішення є

DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

Якщо писати так, я отримую таку ж помилку

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
    })
alert.addAction(defaultAction)

present(alert, animated: true, completion: nil) 

Я отримую таку ж помилку

Presenting view controllers on detached view controllers is discouraged <MyAppName.ViewController: 0x7fa95560Z070>.

Повне рішення є

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
     })
alert.addAction(defaultAction)
//Made Changes here    
DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

Запуск його через DispatchQueue, як це працював для мене. Я роблю performSegue до контролера модального перегляду, викликаного з viewDidLoad на моєму першому контролері перегляду (вступний екран першого запуску для орієнтування нових користувачів). Він завантажувався чудово, але генерував попередження. Обгортання виклику performSegue у виклику асинхронізації DispatchQueue виключає попередження. Дякую!
Грант Нойфельд

1

Переконайтеся, що у вас є контролер кореневого виду для початку. Ви можете встановити його didFinishLaunchingWithOptions.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [window setRootViewController:viewController];
}

1

Дуже багато причин для цього попередження. Моє через те, що у мене підключений канал з ViewController до іншого, який буде представлений модально. Але, ViewController, з якого я представляю, динамічно генерується PageViewController. Ось чому він відокремлений у дошці розкадрувань. Мій додаток через це не вийде з ладу; але я хотів би замовкнути попередження.


1

Я дійшов до цього потоку, де у мене є спеціальна панель навігації, і через неї я викликав AlertViewController.

Мені довелося додати його в дитинстві до мого основного контролера перегляду. Тоді я міг би зателефонувати презентувати це без будь-якого попередження.

Ви повинні додати свою Zoomed Image View Controllerдитину як основного ViewController.

(наприклад)

[self addChildViewController:ZoomedImageViewController];

Тоді ви зможете зателефонувати до свого ZoomedImageViewController

[self presentViewController:ZoomedImageViewController];

1

Багато відповідей вірні.

  • Перевірте, чи є у вашої презентаціїViewController батьківський вигляд або контролю, чи ні.
  • Якщо ні, додайте його десь і слід додати
  • інше, переконайтеся, що у parentViewController є parentViewController рекурсивно, поки у кожного viewController немає батьківського

Ця проблема трапилася зі мною, коли мій колега додав AViewController до BViewController. Якось він просто додає подання AViewController до подання BViewController.

Виправлено додаванням bViewController.addChild (aViewController)


1
Дякую! додавання addChild до мого блоку завершення Hero.shared.transition повністю вирішило мою проблему.
landnbloc

0

Це залежить від того, чи хочете ви показати своє сповіщення чи щось подібне в будь-якому місці роду UIViewController.

Ви можете використовувати цей приклад коду:

UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Example" preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil];

[alert addAction:cancelAction];


[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alert animated:true completion:nil];

З вашим кодом він не працює, і він дає цей журналAttempt to present <UIAlertController: 0x7fc01a1eb600> on <ViewController: 0x7fc019821e00> whose view is not in the window hierarchy!
Naveed Abbas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.