How to find current visible viewController in iOS - ios

We know , if your viewController have been contain UINavigationController ,
you can find your current visible view controller by 'self.navigationController.visibleViewController' .
But I you present a view controller , how to find current visible controller ?
For Example :
code one :
------
AVClr *avclr = [[AVClr alloc]init] ;
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate ;
appDelegate.window.rootViewController = avclr ;
[avclr presentViewController:loginNavClr animated:YES completion:nil] ;
---> now , display avclr
code two:
------
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate ;
UIViewController *currentVisibleViewController = appDelegate.window.rootViewController ;
BVClr *bvclr = [[BVClr alloc]init] ;
[currentVisibleViewController presentViewController:bvclr animated:YES completion:nil] ;
---> now , display bvclr
code three:
------
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate ;
UIViewController *currentVisibleViewController = appDelegate.window.rootViewController ;
CVClr *cvclr = [[CVClr alloc]init] ;
[currentVisibleViewController presentViewController:cvclr animated:YES completion:nil] ;
---> Error , can not display cvclr , because avclr is a rootViewController and avclr present bvclr , so display bvclr .
Question:
But we know ,code three in another .m file , so we don't know who is the rootViewController . so If I present cvclr , the result is unexpect !
In the circumstances ,how to display cvclr

-(UIViewController *)getVisibleViewController : (UIViewController *)rootViewController
{
UIViewController *rootVC = rootViewController;
if (rootVC == nil)
{
rootVC = [[[UIApplication sharedApplication] keyWindow] rootViewController];
}
if ([rootVC presentedViewController] == nil)
{
return rootVC;
}
if ([rootVC presentedViewController] != nil)
{
if ([[rootVC presentedViewController] isKindOfClass:UINavigationController.self]) {
UINavigationController *navigationController = (UINavigationController *)[rootVC presentedViewController];
return [[navigationController viewControllers] lastObject];
}
return [self getVisibleViewController : [rootVC presentedViewController]];
}
return nil;
}

to find current top view controller i used 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;
}

If you are presenting the next screen from that class then you don't need to fetch top view controller from UIWindow
Simply use this..
-----------------
AVClr *avclr = [[AVClr alloc]init];
[self presentViewController: avclr animated:YES completion:nil] ;
------------------------------
BVClr *bvclr = [[BVClr alloc]init] ;
[self.presentingViewControler presentViewController:bvclr animated:YES completion:nil] ;
------------------
CVClr *cvclr = [[CVClr alloc]init] ;
[self.presentingViewControler presentViewController:cvclr animated:YES completion:nil] ;

This code also check UITabbarViewContoller :
-(UIViewController *) getVisibleViewContoller {
UIViewController *rootViewController = UIApplication.sharedApplication.keyWindow.rootViewController;
if (!rootViewController) {
return nil;
}
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tabbarVC = (UITabBarController *) rootViewController;
UIViewController *selectedVC = tabbarVC.selectedViewController;
if (selectedVC) {
if (![selectedVC isKindOfClass:[UINavigationController class]]) {
return selectedVC;
}
rootViewController = selectedVC;
}
}
if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationVC = (UINavigationController *) rootViewController;
if (navigationVC.topViewController) {
return navigationVC.topViewController;
}
return navigationVC.viewControllers.lastObject;
}
return rootViewController;
}

Related

transitionViewForCurrentTransition is not set, presentation controller was dismissed during the presentation

TransitionViewForCurrentTransition is not set, presentation controller was dismissed during the presentation? (<_UIFullscreenPresentationController:
how to solve it, no exception is printing but above error show on calling
-(IBAction)presume:(id)sender
{
[self returnToRootViewController];
}
- (UIViewController*)topmostViewController
{
UIViewController* vc = [[[UIApplication sharedApplication] keyWindow] rootViewController];
while(vc.presentedViewController) {
vc = vc.presentedViewController;
}
return vc;
}
- (void)returnToRootViewController
{
UIViewController* vc = [self topmostViewController];
while (vc) {
if(vc.presentingViewController) {
if ([vc isKindOfClass:[CarDetailVC class]])
{
#try {
[vc dismissViewControllerAnimated:NO completion:^{}];
} #catch (NSException *exception) {
NSLog(#"exception=%#",exception);
} #finally {
}
}
}
vc = vc.presentingViewController;
}
}
Let's start with a more direct path to the target vc (the instance of CarDetailVC).
- (UIViewController*)vcWithClass:(Class)klass {
UIViewController* vc = [[[UIApplication sharedApplication] keyWindow] rootViewController];
while(![vc.presentedViewController isKindOfClass:klass]) {
vc = vc.presentedViewController;
}
return vc;
}
Now, get to it and dismiss the vc it presented.
- (void)returnToCarVC {
CarDetailVC *carVC =(CarDetailVC*) [self vcWithClass:[CarDetailVC self]];
UIViewController *presented = carVC.presentedViewController;
[presented dismissViewControllerAnimated:NO completion:^{}];
}

How to identify the screen name or view controller in IOS app

I am automating IOS app test cases using Appium. I have a scenario in which I have to identify.. i am on which screen so that I can close the screen
In broader view , we have a inapp notification in our app which get open in random way.
So I can handle these condition if I would be able to identify the current screen.
I handle the same thing in Android using driver.currentActivity method
I need the some kind of same method for IOS apps
you get top most view controller by using below method
+ (UIViewController*) topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
Or if you have navigation or UIabbar controller then use below method to get visible view controller
- (void)applicationWillResignActive:(UIApplication *)application
{
UIViewController *vc = [self visibleViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)visibleViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil)
{
return rootViewController;
}
if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]])
{
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self visibleViewController:lastViewController];
}
if ([rootViewController.presentedViewController isKindOfClass:[UITabBarController class]])
{
UITabBarController *tabBarController = (UITabBarController *)rootViewController.presentedViewController;
UIViewController *selectedViewController = tabBarController.selectedViewController;
return [self visibleViewController:selectedViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self visibleViewController:presentedViewController];
}

iOS - Navigational flow is missed

In my application i am adding the child view controller using the following code.
self.onlineUserList = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"OnlineUserList"];
UINavigationController *navController=[[UINavigationController alloc]initWithRootViewController:self.onlineUserList];
self.onlineUserList.delegate = self;
navController.navigationBar.hidden = YES;
CGRect aRect = [[UIScreen mainScreen] bounds];
[navController.view setFrame:(CGRect){0, 0, aRect.size.width, aRect.size.height-47}];
[self addChildViewController:navController];
[self.view addSubview:navController.view];
[self didMoveToParentViewController:navController];
And i am removing the child view controller using following code.
[_onlineUserList removeFromParentViewController];
[_onlineUserList.view removeFromSuperview];
[_onlineUserList didMoveToParentViewController:nil];
It is working well. But after removing the child view controller then i am not able to do any action on the parent view controller. I think i am missing some thing navigational flow. Please help me.
Just get all Viewcontrollers in array , check this .
If you want all view controller of navigation ,
NSArray *currentControllers = self.navigationController.viewControllers;
if you want first pushedviewcontroller ,
UIViewController *firstcontroller = self.navigationController.viewControllers.firstObject;
if you want last object ,
UIViewController *Lastcontroller = self.navigationController.viewControllers.lastObject;
Now trace with this code , which viewcontroller you are removing .
or Another way is just give identifier of your parentviewcontroller in didfinishlaunchwithoption , like ,
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
SlideMenu = [storyboard instantiateViewControllerWithIdentifier:#"SlideMenu"];
then add method for topviewcontroller,
- (UIViewController *)topViewController{
return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil) {
return rootViewController;
}
if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self topViewController:lastViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self topViewController:presentedViewController];
}
now create one more method in your appdelegate to present your parentviewcontroller like ,
- (void)ShowMenu{
[SlideMenu ShowToViewController:[self topViewController]];
}
and then when you remove childviewcontroller then call ,
[[AppDelegate mainDelegate] ShowMenu];
I hope this info enough to solve your issue.

UIAlertViewController Error

How can I use UIAlertViewController in appdelegate class.
if you want to show in UIAlertviewController in Appdelegate, you can do it two ways
Choice-1
Initially you get the visible/Top ViewController from window , assume that you were in some where on any viewcontrollerm at that time you access that from root view controller , use this
UIViewController *vc = [self visibleViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
//second add your present on`UIAlertController`
[vc presentViewController:alert animated:YES Completion:nil];
For get which viewcontroller at visible for Reference purpose I take the answer From here
- (UIViewController *)visibleViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil)
{
return rootViewController;
}
if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]])
{
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self visibleViewController:lastViewController];
}
if ([rootViewController.presentedViewController isKindOfClass:[UITabBarController class]])
{
UITabBarController *tabBarController = (UITabBarController *)rootViewController.presentedViewController;
UIViewController *selectedViewController = tabBarController.selectedViewController;
return [self visibleViewController:selectedViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self visibleViewController:presentedViewController];
}
Swift
let navigationController = application.windows[0].rootViewController as UINavigationController
let vc = navigationController.visibleViewController
vc.presentViewController(alert, animated: true, completion: nil)
Choice-2
If you want to present the UIAlertController in directly in Appdelegetae , do like simple
[self.window.rootViewController presentViewController:alert animated:YES Completion:nil];
Update
[ [[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:alert animated:YES Completion:nil];

Get reference to top viewcontroller in iOS

How do I get reference to top visible view controller in my app. I saw some solutions which make use of navigationcontroller.[top|visible]viewcontroller. But I don't use navigation controllers in my app.
This seems like a pretty common use case, and I find it strange it is difficult to get access to top|visible view controller
This should also follow your modal views and navigation controllers (if any):
- (UIViewController *)deepestPresentedViewControllerOf:(UIViewController *)viewController
{
if (viewController.presentedViewController) {
return [self deepestPresentedViewControllerOf:viewController.presentedViewController];
} else {
return viewController;
}
}
- (UIViewController *)topViewController
{
UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
UIViewController *deepestPresentedViewController = [self deepestPresentedViewControllerOf:rootViewController];
if ([deepestPresentedViewController isKindOfClass:[UINavigationController class]]) {
return ((UINavigationController *)deepestPresentedViewController).topViewController;
} else {
return deepestPresentedViewController;
}
}
You should probably be using the delegate pattern here (giving the child view controller a reference to an object that it can call on). If you edit your post to explain why you think you need a reference to the top view controller, we can give you advice about how to use the delegate pattern in your situation.
But for now I'll just give you the rope you need to hang yourself:
UIViewController *topVC = [UIApplication sharedApplication].keyWindow.rootViewController;
-(UIViewController *)getCurrentViewController
{
UIViewController *result = nil;
UIWindow * window = [[UIApplication sharedApplication] keyWindow];
if (window.windowLevel != UIWindowLevelNormal)
{
NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow * tmpWin in windows)
{
if (tmpWin.windowLevel == UIWindowLevelNormal)
{
window = tmpWin;
break;
}
}
}
UIView *frontView = [[window subviews] objectAtIndex:0];
id nextResponder = [frontView nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]])
result = nextResponder;
else
result = window.rootViewController;
return result;
}
-(UIViewController *) getTopMostController
{
UIWindow *topWindow = [UIApplication sharedApplication].keyWindow;
if (topWindow.windowLevel != UIWindowLevelNormal)
{
topWindow = [self returnWindowWithWindowLevelNormal];
}
UIViewController *topController = topWindow.rootViewController;
if(topController == nil)
{
topWindow = [UIApplication sharedApplication].delegate.window;
if (topWindow.windowLevel != UIWindowLevelNormal)
{
topWindow = [self returnWindowWithWindowLevelNormal];
}
topController = topWindow.rootViewController;
}
while(topController.presentedViewController)
{
topController = topController.presentedViewController;
}
if([topController isKindOfClass:[UINavigationController class]])
{
UINavigationController *nav = (UINavigationController*)topController;
topController = [nav.viewControllers lastObject];
while(topController.presentedViewController)
{
topController = topController.presentedViewController;
}
}
return topController;
}
-(UIWindow *) returnWindowWithWindowLevelNormal
{
NSArray *windows = [UIApplication sharedApplication].windows;
for(UIWindow *topWindow in windows)
{
if (topWindow.windowLevel == UIWindowLevelNormal)
return topWindow;
}
return [UIApplication sharedApplication].keyWindow;
}

Resources