Keywords: iOS | view controller | warning
Abstract: This article explores the iOS warning 'Presenting view controllers on detached view controllers is discouraged,' common in iOS 7 and later. It analyzes causes, such as improper view hierarchy attachment, and provides solutions, focusing on using parentViewController for safe presentation, with additional references to using rootViewController and waiting for viewDidAppear. The article aims to help developers understand and avoid this warning, ensuring application stability and compatibility.
Introduction
In iOS development, presenting view controllers is a fundamental task for modal dialogs or detailed views. However, starting with iOS 7, developers may encounter a warning message: Presenting view controllers on detached view controllers is discouraged. This warning is logged to the console and indicates that the view controller from which you are presenting is not properly attached to the view hierarchy, which can lead to unpredictable behavior or application crashes if ignored.
Problem Description
The warning specifically arises when using methods like presentViewController:animated:completion: on a view controller that is considered "detached." A detached view controller is one that is not fully integrated into the view hierarchy, such as a child view controller whose view is not yet visible or is part of a non-full-screen layout. This issue is more prominent in iOS 7 and later versions due to changes in view controller lifecycle management.
Cause Analysis
The primary cause of this warning is attempting to present a view controller from a view controller that is not the root or a properly attached parent. Common scenarios include:
- Presenting from a child view controller without using its parent.
- Trying to present before the view has fully appeared, such as in
viewWillAppear:. - Using a view controller that is part of a custom container with a non-standard view size.
As highlighted in the community answers, presenting from a detached controller can confuse the iOS window system, leading to the warning.
Solution Using parentViewController
The most effective solution, as recommended in the best answer, is to present the view controller from the parent view controller. This ensures that the presentation occurs from a view controller that is properly attached to the view hierarchy. Here is the corrected approach:
[self.parentViewController presentViewController:viewController animated:YES completion:nil];And to dismiss the presented controller, use:
[self dismissViewControllerAnimated:YES completion:nil];This method is particularly useful when dealing with child view controllers in navigation or tab-based interfaces. By accessing parentViewController, you delegate the presentation to a higher-level controller, avoiding detachment issues.
Additional Solutions
Other answers provide alternative strategies:
- Using rootViewController: As suggested in Answer 1, you can present from the root view controller of the window, especially in push navigation scenarios:
[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];This approach is suitable when a global presentation is needed. - Waiting for viewDidAppear: Answer 2 advises to ensure that the view has fully appeared before presenting. Avoid calling presentation methods in
viewWillAppear:or earlier; instead, useviewDidAppear:to guarantee that the view controller is attached.
These methods complement the primary solution and can be chosen based on specific application contexts.
Code Example and Explanation
To illustrate, consider a scenario where you have a child view controller within a navigation controller. When a button is tapped to show a zoomed image, instead of presenting directly from the child, use the parent. Here is a rewritten code snippet based on the core concept:
// Assume 'self' is a child view controller
UIViewController *zoomedImageViewController = [[UIViewController alloc] init];
// Configure the view controller...
[self.parentViewController presentViewController:zoomedImageViewController animated:YES completion:^{
// Completion handler
}];In this example, self.parentViewController refers to the navigation controller or another parent, ensuring that the presentation is handled by an attached controller. This avoids the warning and maintains proper view lifecycle management.
Conclusion
The warning 'Presenting view controllers on detached view controllers is discouraged' serves as a reminder to follow iOS best practices for view hierarchy management. By using parentViewController or similar techniques, developers can ensure safe and predictable view controller presentations. Always test in iOS 7 and later to catch such issues early, and refer to community solutions for robust implementation.