Presenting an alert from a view controller that has closed - ios

I have an iOS Objective-C application in which I am attempting to show a UIAlertController, from a UIViewController which is in the process of closing. I have tried adding this common workaround in AppDelegate:
- (UIViewController *)currentTopViewController
{
UIViewController *topVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (topVC.presentedViewController)
{
topVC = topVC.presentedViewController;
}
return topVC;
}
Called with:
[appDelegate.currentTopViewController presentViewController:alert animated:YES completion:nil];
However this error is still appearing:
Warning: Attempt to present UIAlertController on MyViewController whose view is not in the window hierarchy!
Can anyone advise?

If you want to display an alert upon closing a viewcontroller, then you can just implement dismiss with completion block and display it there. For example:
[self dismissViewControllerAnimated:YES completion:^(void) {
// UIAlertController code here
}];

You can use UIWindow with a transparent UIViewController and then presenting the UIAlertController on it.
Below link provides a category on UIAlertController that has a show method in Objective-C. You can use it.
Link: https://stackoverflow.com/questions/26554894/how-to-present-uialertcontroller-when-not-in-a-view-controller

Related

Present alert controller in main app window?

In my model class i want to show alert when something bad happen (for example, server send an error). However, i dont want to bother with delegate or KVO.
Is there an easy way to show an alert for "main" window, to place a view above others?
Currently i use this code (not work, if placed out of viewController classes):
UIAlertController *vc = [UIAlertController alertControllerWithTitle:#"Произошла ошибка"
message:response
preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:vc animated:YES completion:^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[vc dismissViewControllerAnimated:YES completion:nil];
});
}];
Obviously, classes that don't have a view cant use:
[self presentViewController:vc animated:YES completion:^{
as per solution of #Ashley Mills You can find top view controller with this method
- (UIViewController *)currentTopViewController
{
UIViewController *topVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (topVC.presentedViewController)
{
topVC = topVC.presentedViewController;
}
if ([topVC isKindOfClass:[UINavigationController class]]) {
return [(UINavigationController *)topVC topViewController];
}
return topVC;
}
show you alert in return object of currentTopViewController method
You need to present the UIAlertController from a UIViewController. If you want the main view controller, you'll need to do this from your application delegate's window's rootViewController.
A nasty way to do this is to refer to UIApplication.sharedApplication().delegate.window.rootViewController
A better way would be to post a notification from your model method and listen for it in the App Delegate
Ideally though you should be looking at passing back an error from your model method to the calling view controller.
Or perhaps you could pass in your current view controller as a parameter to the model method

Creating modal view from another modal view fails

In a view that was created modally, pressing a button causes the modal view to be dismissed and another modal view to load.
- (void)loadLanguageSelectionView {
[self dismissViewControllerAnimated:YES completion:nil];
UIViewController *languageSelectionController = [[LanguageSelectionViewController alloc] initWithNibName:nil bundle:nil];
[languageSelectionController setModalPresentationStyle:UIModalPresentationCustom];
[languageSelectionController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:languageSelectionController animated:YES completion:nil];
}
The following error is thrown when this code block executes:
DenkoStation[4259:73173] Warning: Attempt to present <LanguageSelectionViewController: 0x7b185430> on <ViewController: 0x79f52e50> whose view is not in the window hierarchy!
What surprises me is the fact that the code was running happily before I made some changes to my code as outlined here.
Where's the mistake?
Because you are trying to present a viewController on top of a viewController which is already dismissed and no longer in window hierarchy.
What you can try is, you can take the ParentViewController reference from current viewController and then you can present new viewController on ParentViewController Like This :
- (void)loadLanguageSelectionView {
UIViewController *parentController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
UIViewController *languageSelectionController = [[LanguageSelectionViewController alloc] initWithNibName:nil bundle:nil];
[languageSelectionController setModalPresentationStyle:UIModalPresentationCustom];
[languageSelectionController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[parentController presentViewController:languageSelectionController animated:YES completion:nil];
}];
}

PushViewController doesn't pushes after dismissingViewController

I am developing iPhone app, where i got stuck at one point.
The error i am facing is, i have one presentViewController on which i have one button, on click of that button i am dismissing my presentViewController and after dismissing i want to push My view controller but it doesn't pushes.
Code on PresentViewController:
- (IBAction)ButtonClick:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
[Obj MethodCall];
}];
}
after dismissing PreviousViewController:
-(void) MethodCall
{
NSLog(#" -- MethodCall Success --");
[self.navigationController pushViewController:[[NewViewController alloc] init] animated:YES];
}
My log shows -- MethodCall Success -- but it does not pushes my view.
Where i am doing mistake ?
Please help and thanks for reading.
The problem with you is I think you are not having UINavigationController as a rootViewController of the viewController from which you have to navigate. So please try to add a UINavigationController as a parent view or rootView of the vieController from which you want to push another viewController.
- (IBAction)ButtonClick:(id)sender {
NewViewController *newView = [[NewViewController alloc] init]
[self presentViewController:newView animated:YES completion:nil];
}

Warning: Attempt to present <MyViewController: 0x10c5771a0> on <UINavigationController: 0x10c533da0> whose view is not in the window hierarchy

I am trying to segue to my ViewController with this code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"iPhone_Storyboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"details"];
[self presentViewController:vc animated:YES completion:nil];
However I get this error message:
Warning: Attempt to present <MyViewController: 0x10c5771a0> on <UINavigationController: 0x10c533da0> whose view is not in the window hierarchy!
I am calling the segue in the UIAlertView Delegate Method:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
}
Your UIAlertView's window is the frontmost UIWindow, so your view controller can't present. You need to wait until the alert view dismisses. The simplest way is to use alertView:didDismissWithButtonIndex: (instead of clickedButtonAtIndrx).
add this too, it worked for me.
lvc.modalPresentationStyle = UIModalPresentationFormSheet;
lvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[mvc presentModalViewController:lvc animated:YES];

Present view controller from app delegate

I'm attempting to present a view controller from the app delegate with this code:
- (void)interstitialViewControllerRequestSucceeded:(UIViewController *)interstitialViewController
{
[self.window.rootViewController presentViewController:(UIViewController *)interstitialViewController animated:YES completion:NULL];
}
It will display the interstitial on the initial view controller but none of the others. I want it to display on every one attached to a navigation controller.
How can I modify this code to achieve that goal?
You can also try:
[[[UIApplication sharedApplication] keyWindow] rootViewController]
How I use it:
#define ROOTVIEW [[[UIApplication sharedApplication] keyWindow] rootViewController]
[ROOTVIEW presentViewController:interstitialViewController animated:YES completion:^{}];
Swift 3 version for checked response :
UIApplication.shared.keyWindow?.rootViewController
Swift 5 and up
Check this:
UIApplication.shared.windows.first?.rootViewController

Resources