ChatGPT解决这个技术问题 Extra ChatGPT

警告:- 不鼓励在分离的视图控制器上显示视图控制器

在我的应用程序中,我使用的是导航控制器。稍后在某些视图中,我使用 presentViewController 显示缩放图像。我也没有使用故事板或笔尖。

我仅在 iOS 7 中收到此错误。它在 iOS 6 及更早版本中运行良好:

不鼓励在分离的视图控制器上呈现视图控制器

我还没弄清楚。但是在我的应用程序中,我没有将任何视图控制器分配给 window.rootviewcontroller。我正在向窗口添加视图。可能这就是我的原因。但不确定...
@GaganJoshi 您上面提到的原因可能不是原因。即使我面临同样的问题。在我们的项目中,我将视图控制器分配给 window.rootviewcontroller 。
我认为其他评论正确地将这与 rootViewController 和窗口连接相关联。我还没有完全弄清楚,但我已经能够通过直接在 rootViewController 上而不是在导航控制器或其子之一上显示控制器来解决这个问题。

c
cdescours

为避免在推送导航中收到警告,您可以直接使用:

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

然后在您的模态视图控制器中,当一切都完成后,您可以调用:

[self dismissViewControllerAnimated:YES completion:nil];


我正在使用此行代码“[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];”呈现图像选择器但无法使用此行“[self dismissViewControllerAnimated:YES completion:nil];”关闭 poicker 视图解雇控制器的任何替代选项
@keyurbhalodiya您需要从modalView调用dismissViewController方法才能使其工作。因此,如果您使用 [viewA.window.rootViewController presentViewController:viewB] 从 viewA 显示名为 viewB 的视图,则需要在 viewB 中添加一个按钮,例如,与调用 [self dismissViewControllerAnimated] 的自定义操作相关联。是不是更清楚了?
在 iOS 8 中不显示视图控制器。
对于 iOS 8:[self.view.window.rootViewController.navigationController
使用 self.navigationController 为我做到了。
A
Azaxis

等待 viewDidAppear()

如果您尝试在视图实际出现之前呈现视图控制器,例如在 viewWillAppear() 或更早版本中呈现视图,也会出现此错误。尝试在 viewDidAppear() 之后或其内部呈现另一个视图。


换句话说,不要在 viewDidLoad() 中显示任何视图控制器,各位!这个错误我犯过很多次了...
谢谢这有帮助。我在 viewDidLoad 中有代码,它试图在最后显示一个对话框。
在我不使用动画进行测试的情况下运行单元/集成测试时出现此错误。
对,就是你说的!如果不是这条消息,我可能不得不重构。
G
Gagan Joshi

这个警告的原因是我在一个不是全尺寸视图的小视图上展示了一个视图控制器。下面给出的是我的项目的图像。点击上面的四个选项。用户导航到不同的 childviewcontroller 的视图。(它像 tabViewcontroller 一样工作)。但是 childviewcontroller 包含小尺寸的视图。因此,如果我们从 childviewcontroller 呈现一个视图,它会给出这个警告。

https://i.stack.imgur.com/slvz5.png

为了避免这种情况,您可以在 childviewcontroller 的父级上显示一个视图

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

[self.view.window.rootViewController.navigationController pushViewController:YOUR_VIEW_CONTROLER 动画:YES];
“在不是全尺寸视图的小视图上呈现视图控制器。” ... 确切地。不错的作品。
K
Kjuly

在我的例子中,我将 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];

顺便说一句,这也适用于从表格视图单元格中显示弹出框的情况,您只需要确保表格视图控制器也已添加为子视图控制器。


另外调用 didMoveToParentViewController。请检查添加和删除 ChildViewController:gist.github.com/tomohisa/2897676
@jianzong 我记得没有必要做最后一步。无论如何,让我添加它,谢谢您的建议。 :)
是的,它可以在没有最后一步的情况下工作。我认为它的目的是通知 parentViewController 以便它会调用一些方法来做某事。 :)
它对我有用,我在另一个控制器中使用一个控制器视图 - (容器视图以编程方式),我没有添加 [self addChildViewController:sampleViewController];,现在我添加了这个,谢谢
J
Jeremie

斯威夫特 3

对于任何绊倒此的人,这里是快速的答案。

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

D
Daniel Ytterbrink

我认为问题在于您没有正确的视图控制器层次结构。设置应用程序的 rootviewcontroller,然后通过在其上推送或呈现新视图控制器来显示新视图。让每个视图控制器管理他们的视图。只有容器视图控制器,如 tabbarviewcontroller,应该将其他视图控制器视图添加到它们自己的视图中。阅读视图控制器编程指南以了解有关如何正确使用视图控制器的更多信息。 https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/


a
averem

我有几乎同样的问题。原因是我试图在另一个上呈现“一些”控制器,动画完成后我将呈现的控制器设置为 root。在此操作之后,所有进一步呈现的控制器都会给我带来警告:“不鼓励在分离的视图控制器上呈现视图控制器”。我解决了这个警告,只是将“某些”控制器设置为 root,一开始没有任何演示。

删除:

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

       [self window].rootViewController = controller;

       [[self window] makeKeyAndVisible];}];

只需以 root 身份制作,无需任何演示:

 [[self window] setRootViewController:controller];

这正是我的问题。试图用 UIModalTransitionStyleCrossDissolve 呈现它,然后使其成为 rootViewController。之后,所有其他演示都失败并显示给定的警告消息。只需将其设置为没有动画的 rootViewcontroller 就可以了。谢谢!
G
Gagan Joshi

解决方案之一是如果您有 childviewcontroller 所以您只需通过给定的方式在其父级上显示viewcontroller

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

并且对于解雇使用相同的解雇视图控制器。

[self dismissViewControllerAnimated:YES completion:nil];

这是对我有用的完美解决方案。


i
itsji10dra

在 iOS 8 中使用 [self.navigationController presentViewController:xxx animated:YES completion:nil]


V
Vlad

试试这个代码

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

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

N
Naresh

在 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 调用(用于定位新用户的首次启动介绍屏幕)。它加载正常,但会产生警告。在 DispatchQueue 异步调用中包装 performSegue 调用可以消除警告。谢谢!
W
Warif Akhand Rishi

如果它是基于 TabBarController 的应用程序,请尝试在 TabBarController 上展示。

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

原因可能是 selfTabBarController 的子级,而您正试图从 ChildViewController 呈现。


M
Mozahler

是的,在显示另一个视图中的警报控制器时,我也遇到了同样的警告消息。后来我通过从父视图控制器中显示警报控制器来避免这种情况,如下所示:

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

J
John Topley

您需要添加将新控制器作为父视图控制器的子级呈现的视图控制器。

假设您有您的MainViewController,然后添加一个名为controllerA 的新控制器,然后您想从controllerA 呈现一个名为controllerB 的新控制器

你必须写这样的东西:

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

在 controllerA 中,您可以在没有警告的情况下展示新的控制器

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

N
Naveed Abbas

我在这个线程上找到了一个自定义导航栏,并通过它调用了一个 AlertViewController。

我不得不将它作为一个孩子添加到我的主视图控制器中。然后我可以在没有任何警告的情况下调用它。

您应该将 Zoomed Image View Controller 添加为主 ViewController 的子项。

(例如)

[self addChildViewController:ZoomedImageViewController];

然后你就可以调用你的 ZoomedImageViewController

[self presentViewController:ZoomedImageViewController];

s
samwize

确保你有一个根视图控制器开始。您可以在 didFinishLaunchingWithOptions 中设置它。

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

L
Lee Probert

这个警告有很多原因。我的是因为我有一个从 ViewController 连接到另一个将以模态方式呈现的 segue。但是,我展示的 ViewController 是由 PageViewController 动态生成的。这就是它在情节提要中分离的原因。我的应用程序不会因此而崩溃;但我想消除警告。


F
Fabio

这取决于您是否想在任何类型的 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!
J
Jerome Li

很多答案都是对的。

检查您的presentingViewController 是否有parentViewController。

如果不是,请将其添加到应添加的位置

否则,检查它的 parentViewController 是否有 parentViewController 递归,直到每个 viewController 都有父

当我的同事将 AViewController 添加到 BViewController 时,我发生了这个问题。不知何故,他只是将 AViewController 的视图添加到 BViewController 的视图中。

通过添加 bViewController.addChild(aViewController) 修复


谢谢!在我的 Hero.shared.transition 完成块中添加 addChild 完全解决了我的问题。