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
Related
I am presenting a view controller programmatically but when the device is rotated it's getting auto-dismissed.
I don't know why it happens and how do I fix it
Here is the code
UINavigationController* navC = blah blah.
ViewContoller* vc = blah blah
[navC setViewControllers:#[vc]];
// Normal case.
if (![[[self window] rootViewController] presentedViewController]) {
[[[self window] rootViewController] presentViewController: navC animated:true completion:nil];
}
I have kept the code in appdelegate
Any help in resolving this is appreciated
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
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
I have implemented this code in AppDelegate.m
-(UIInterfaceOrientationMask) application:(UIApplication *)application supportedInterfaceOrientationsForWindow :(UIWindow *)window
{
UIViewController *currentVC = [(UINavigationController *)[UIApplication sharedApplication].delegate.window.rootViewController topViewController];
if ([currentVC isKindOfClass:[VideoPlayerVC class]])
{
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
and pushing to the VideoPlayerVC with link like this :
NSURL *link = [NSURL URLWithString:strUrl];
VideoPlayerVC *vc = [[VideoPlayerVC alloc] init];
vc.videoUrl = link;
[self.navigationController pushViewController:vc animated:false];
This allows me to enable autorotate in the VideoPlayer ViewController but when the video playback ends in Landscape mode, the entire app is being converted into Landscape view mode only.
Please help me guys to fix the issue.
Thanks in advance.
The system only tries to invalidate your orientation when a full screen modal presentation happened or dismissed. So I suggest you to replace your [self.navigationController pushViewController:vc animated:false]; with [self presentViewController:vc animated:YES completion:nil];
And if your UE needs the navigation transition, you can try to mimic it with UIViewControllerContextTransitioning customization.
Also there is a tricky method if you must use push behavior(It's the only one method not using private api as I know)
Every time you push/pop from the navigation stack, call the code below:
[[vc presentViewController:[UIViewController new] animated:NO completion:^(BOOL completed){
[vc dismissViewControllerAnimated:NO completion:nil];
}];
The code try to make an invisible vc and dismiss it immediately to make iOS update the supported orientation.
I have a code like this to present a TOWebViewController that contain URL to my company web page.
TOWebViewController *webViewController = [[TOWebViewController alloc] initWithURL:url];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:webViewController];
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:navigationController];
After its open how I get back to my previous view or dismiss the root view controller since my navigator bar only show grey bar.
thanks
Use [self presentViewController:imagePickerController animated:YES completion:nil]; instead.And don't use root view controller!
you need to create a custom back button #selector and in it you need to set [[[[UIApplication sharedApplication] delegate] window] setRootViewController:previousViewController];
though you need the reference of your previous viewController, however i won't recommend this approach.As #lumialxk said, use this instead [self presentViewController:imagePickerController animated:YES completion:nil];