I have a UIViewController that presents a UIAlertController. I would like the UIAlertController to dismiss itself while still allowing the UIAlertController to stay on top.
Here's the code to dismiss:
[self dismissViewControllerAnimated:YES completion:nil];
I'll omit the code for UIAlertController, but I'm using this code to present:
[self presentViewController:alert animated:YES completion:nil];
I'm looking for a solution that can be contained within my single UIViewController subclass.
I suppose your scenario is like this:
A_ViewController pushed B_ViewController, B_ViewController presented alertController at some circumstances. Now you're at B_ViewController and want to dismiss itself without the alert disappear,right?
If I got this right,I don't think this gonna work. Because alert depends on B_ViewController, if B is gone, so did alert.
Here is my thought:
A_ViewController pushed B_ViewController, now we're at B, at some circumstances there should be an alert being presented,instead of letting B present the alert, we could let A present the alert(We could use delegate method to tell A to present an alert). And now, B and alert are independent,B gone,alert stays.
I hope this would help.
im have two view controller UserListView and UserProfileView!
in UserListView view controller i'm have a button for swtich to UserProfileView and here is code.
UserListView.m - Click Action
- (IBAction)SettingClick:(id)sender
{
UserList *UserProfile = [self.storyboard instantiateViewControllerWithIdentifier:#"UserProfileView"];
[self presentViewController:UserProfile animated:YES completion:nil];
}
And code working fine, when user switch to profile (UserProfileView) have a close button back to UserListView and here is code.
UserProfileView.m - Close click action
- (IBAction)CloseClick:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
UserProfile *UseList = [self.storyboard instantiateViewControllerWithIdentifier:#"UserListView"];
[self presentViewController:UseList animated:YES completion:nil];
}
in this code i will using [self dismissViewControllerAnimated:YES completion:nil]; to close UserProfileView view controller for low ram usage and it work.
But affter i close UserProfileView i want to open this view controller again and it do not work, UserProfileView not showing again??
i using xcode 5 and building an App for ios 7, please help.
Thanks for your time.
If I understand correctly, when you call SettingClick: your app is displaying a UserList. So, when you dismiss a view controller presented on top of it, you should go back to UserList without the need for presenting it again. So you can try with:
- (IBAction)CloseClick:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
This will work unless you had originally presented UserList as well. In this case, UserList will be dismissed with the top controller. In this case, you can delay presenting a second time UserList after dismissing UserProfile, and it should work.
In the latter case, I would suggest you to use a navigation controller instead of simply presenting your controllers like you are doing. As you see, it is not really straightforward and you will get into catches of any kind. Presenting a controller works ok when you present just one controller at a time. On the other hand, if you instantiate a UINavigationController, this will handle the controllers' hierarchy for you.
use this -
- (IBAction)CloseClick:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
This will return to your previous view when u click that button that has been linked with this action
I'm having an app crash in iOS7, but is working on iOS6. While debugging the next code from my AppDelegate, I checked that in iOS7 the next function is executed and then the modal view controller is loaded.
- (void)presentModalWebViewWithURL:(NSURL *)url title:(NSString *)title
{
[self.modalWebViewController dismissModalViewControllerAnimated:YES];
self.modalWebViewController = [[[MyModalWebViewController alloc] initWithURL:url] autorelease];
self.modalWebViewController.title = title;
UINavigationController *nav = [self.modalWebViewController modalNavigationControllerWithTarget:self dismissSelector:#selector(dismissModalWebView)];
[self.window.rootViewController presentViewController:nav animated:YES completion:NULL];
}
In iOS6, I checked that the function stops the execution in the last line until the modal view controller is loaded.
What happens in iOS7 is that when the modal view controller tries to load running viewWillAppear, I was able to check that the modal view controller has changed all the values and even the properties are pointing to objects of different types. I guess that they are being deallocated but I can't figure out why and how to fix it. Any suggestions?
When you dismiss a modal view controller, you're supposed to call the dismiss method on the view controller that presented the view controller. Also the dismissModalViewControllerAnimated: method is deprecated, you should instead use dismissViewControllerAnimated:completion:. So looking at your code, you should probably be calling the dismiss method on self.window.rootViewController, since that's what you're presenting modal views from.
Also, not knowing how the rest of your code looks, I'm assuming the first time this gets called, self.modalWebViewController is nil, so you probably want to check if self.modalWebViewController is set to something before you call dismiss, and also to set it to nil any time you do dismiss it.
In my app, I am using a navigation controller. Later on in some view I am using presentViewController for showing a zoomed image.
Also I am not using a Storyboard or nib.
I am getting this error in iOS 7 only. It works fine in iOS 6 and earlier:
Presenting view controllers on detached view controllers is
discouraged
To avoid getting the warning in a push navigation, you can directly use :
[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];
Wait for viewDidAppear():
This error can also arise if you are trying to present view controller before view actually did appear, for example presenting view in viewWillAppear() or earlier.
Try to present another view after viewDidAppear() or inside of it.
The reason of this warning is i was presenting a view controller over a small view that is not full size view. Given below is the image of my project. where on click on four option above. User navigate to different childviewcontroller's view.(it works like tabViewcontroller). But the childviewcontroller contains view of small size. So if we present a view from childviewcontroller it gives this warning.
And to avoid this, you can present a view on childviewcontroller's parent
[self.parentViewController presentViewController:viewController animated:YES completion:nil];
In my case, I've a sampleViewController's view added as a subview, then tries to present a popover from the view of sampleViewController (here self instead a UIViewController instance):
[self.view addSubview:sampleViewController.view];
The right way should be below:
// 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];
B.t.w., this also works for the case that present a popover form a tableview cell, you just need to make sure the tableview controller has been added as child view controller as well.
Swift 3
For anyone stumbling on this, here is the swift answer.
self.parent?.present(viewController, animated: true, completion: nil)
I think that the problem is that you do not have a proper view controller hierarchy. Set the rootviewcontroller of the app and then show new views by pushing or presenting new view controllers on them. Let each view controller manage their views. Only container view controllers, like the tabbarviewcontroller, should ever add other view controllers views to their own views. Read the view controllers programming guide to learn more on how to use view controllers properly. https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/
I have almost the same problem. The reason was that I tried to present "some" controller on another and after animation was completed I was setting presented controller as root. After this operation all further controllers presenting bring me to the warning: "Presenting view controllers on detached view controllers is discouraged". And I solve this warning just settings "some" controller as root without any presentation at the begin.
Removed:
[[self rootController] presentViewController:controller animated:YES completion:^{
[self window].rootViewController = controller;
[[self window] makeKeyAndVisible];}];
Just make as root without any presentation:
[[self window] setRootViewController:controller];
One of the solution to this is if you have childviewcontroller So you simply presentviewcontroller on its parent by given
[self.parentViewController presentViewController:viewController animated:YES completion:nil];
And for dismiss use the same dismissview controller.
[self dismissViewControllerAnimated:YES completion:nil];
This is perfect solution works for me.
Use [self.navigationController presentViewController:xxx animated:YES completion:nil] in iOS 8.
In Swift 4.1 and Xcode 9.4.1
The solution is
DispatchQueue.main.async(execute: {
self.present(alert, animated: true)
})
If write like this i'm getting same error
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)
I'm getting same error
Presenting view controllers on detached view controllers is discouraged <MyAppName.ViewController: 0x7fa95560Z070>.
Complete solution is
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)
})
Try this code
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:<your ViewController object>];
[self.view.window.rootViewController presentViewController:navigationController animated:YES completion:nil];
Try presenting on TabBarController if it is a TabBarController based app .
[self.tabBarController presentViewController:viewController animated:YES completion:nil];
Reason could be self is child of TabBarController and you are trying to present from a ChildViewController.
Yes, I also faced the same warning message while displaying an Alert controller which was in another view. Later on I avoided this by presenting the alert controller from the parent view controller as below:
[self.parentViewController presentViewController:alertController animated:YES completion:nil];
you need to add the view controller that will present the new controller as a child of the parent view controller.
Let's say you have yourMainViewController, then you add a new controller called controllerA, and then you want to present a new controller called controllerB from controllerA
you have to write something like this:
[self addChildViewController:controllerA]; //self is yourMainViewController
[self.view addsubView:controllerA.view];
and within controllerA you can present the new controller without warnings
[self presentViewController:controllerB animated:YES completion:nil]; //self is controllerA
I reached on this thread where I have a Custom Navigation Bar and I was calling an AlertViewController through it.
I had to add it as a child to my main view controller. Then I could call present it without any warning.
You should add your Zoomed Image View Controller as a child of the main ViewController.
(e.g)
[self addChildViewController:ZoomedImageViewController];
Then you'd be able to call your ZoomedImageViewController
[self presentViewController:ZoomedImageViewController];
Make sure you have a root view controller to start with. You can set it in didFinishLaunchingWithOptions.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window setRootViewController:viewController];
}
Lots of reasons for this warning. Mine is because I have a segue connected from a ViewController to another that will be presented modally. But, the ViewController I am presenting from is being dynamically generated by a PageViewController. Which is why it is detached in the Storyboard. My app isn't going to crash because of it; but I would like to silence the warning.
It depends if you want to show your alert or something similar in anywhere of kind UIViewController.
You can use this code example:
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];
Many answers are right.
Check your presentingViewController have parentViewController or not.
If no, add it to somewhere it should be added
else, check it's parentViewController has parentViewController recursively until every viewController has parent
This issue happened to me when my co-worker add a AViewController to BViewController. Somehow, he just add the AViewController's view to BViewController's view.
Fixed by add bViewController.addChild(aViewController)
I am doing Preferences feature with UIModalPresentationFormSheet with following code in iPad.
self.preferencesViewController = [[PreferenceViewController alloc] initWithNibName:#"PreferenceViewController" bundle:nil];
self.preferencesViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:self.preferencesViewController animated:YES];
When i save preferences and dismiss view controller with
[self dismissModalViewControllerAnimated:YES];
But my preferences is not change.
i write my check preferences coding in viewWillAppear , however viewWillAppear event is not work with UIModalPresentationFormSheet.
I am fine when i use with
self.preferencesViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:self.preferencesViewController animated:YES completion:nil];
Where can i check event for UIModalPresentationFormSheet?
Thanks for your help.
The standard way to get information back to a controller that created you, is to use a delegate protocol. Your preferenceViewController should define a delegate protocol, and the presenting controller should set itself as the delegate before it presents the preferences controller. When you initiate the save of the preferences, PreferenceViewController should send it's delegate a message saying that it's finished and should be dismissed. In the implementation of that delegate method in the presenting controller, it can then read the preferences from where you saved them, and dismiss the PreferenceViewController.