The entrance of my app is a UINavgationViewController. The root view controller is a UITabBarViewController. The UITabBarViewController contains some normal UIViewControllers. These controllers may call:
self.navgationController.pushViewcontroller(otherViewController, animated:true);
However, I have another thread running in the background. How can I know which view controller is currently being shown on the main screen?
I tried to call UIApplication.keywindows.rootviewcontroller but it returns UINavgationViewController.
UINavgationViewController.viewcontrollers.count == 1, it only contains a UITabBarViewController.
I think you can get the selected view controller from your tab bar:
navigationController.tabBarController.selectedViewController
try by using viewDidAppear method in every view controller class
- (void)viewDidAppear:(BOOL)animated
{
NSLog(#"Currennt view:%#",self);
}
self returns name of ViewController class
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"%#",appDelegate.navController.topViewController);
You can get the top most Controller that is pushed.
Related
I have a viewController A which will both added into viewController hierarchy by being pushed by view B(presented) and being pushed by view C(pushed).
ROOT->...-(-present-)->B-(-push-)->A
ROOT->...-(-push-)->C-(-push-)->A
And now I have a button in viewController A which needs to change the window.rootViewController, but I cannot make it functions correct in both conditions.
When I use [self.navigationController popToRootViewControllerAnimated:<#(BOOL)#>];, it will not dismiss the presented view B.
Also [[[UIApplication sharedApplication] keyWindow].rootViewController dismissViewControllerAnimated:YES completion:<#^(void)completion#>]; is not the solution, because when there is no presented view completion block will not be called.
If I combine those two methods, I think it will work only when I pass a parameter to every viewController in the hierarchy.
So is there a rough way to clear the viewController hierarchy?
Or is there any other solution?
You can set rootViewController from anywhere in application like,
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
appDelegate.window.rootViewController = #"desired root VC"; // instatntiate your VC and set as root VC of your window
And don't forget to implement AppDelegate.h in that class.
I want to navigate to the initial view from almost any View Controller in my storyboard. I don't want to create a segue manually for every view to the initial view. Is there a nice and handy way to do this in one line, or maybe a method that my other VC could inherit?
The best way to do this (in my opinion) would be using a UINavigation Controller.
Make the UINavigation Controller the root view controller of your storyboard, then connect it to your "actual" root view controller.
Then, from any view controller that has been pushed with the navigation controller, you can do:
[self.navigationController popToRootViewControllerAnimated:YES]; // or NO
You can keep a strong reference to the initial/root view controller you want in the AppDelegate, and then setup a method within it that you call from anywhere to switch the current view controller to your initial controller.
You would do something like this in the AppDelegate.h file:
#property (strong, nonatomic) MyInitialViewController *initialViewController
- (void)switchToInitialViewController;
In the AppDelegate.m you can do:
- (void)switchToInitialViewController
{
self.window.rootViewCotroller = self.initialViewController;
}
And then you can do this from any method:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate switchToInitialViewController];
And that, hopefully, helps. :)
Why don't you go for
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifer isEqualToString:#"identifier"]) {
// Put your code here....
}
}
Every ViewController have this kind of method inside and you can move to other controller or your intial Controller. and if you're using NavigationController then you can go for
#Eric answer.
i have a navigation controller which is my application's root view controller. it is my main screen. I have a split view controller whose master view lists location and detail view shows the location on the map. I wanted to push the split view controller to the navigation controller, but it throw a error saying split view controller cant be pushed to navigation controller and it must be application's root view controller.
So i tried a hard way.
MyAppDelegate *myappdelegate= [[UIApplication sharedApplication] delegate];
UISplitViewController * vc= [[UISplitViewController alloc] init];
vs.viewControllers = [NSArray arraywithObjects......
....
myappdelegate.window.rootViewController= vc;
This works. It shows split view controllers without animation as expected. And i do the same steps when i was closing split view controller. i am creating a navigation controller with main screen nib and setting this my app delegate's window.rootviewController again.
And it succesfully loads main screen again.
But i suspect that this is the proper way of achieving this. Is there more eligible way of doing this?
And i couldnt release split view controller's child controllers. i made a breakpoint on my release method of child controllers. it wasnt be catched. I assumed that when i set my app's root view controller as navigation controller, the old root view controller (split view controller) must be released along with its childs.
Then i tried below code when closing split view controller.
UISplitViewController *oldviewcontroller= (UISplitViewController*) myappdelegate.window.rootViewController;
for (UIViewController *child in oldviewcontroller.viewControllers)
{
[child release];
}
//Setting the navigation controller as window.rootviewController again in here.
This code throw an error saying "[UIImageView __viewDidDisappear:]: unrecognized selector sent to instance 0x7d...."
i think because of releasing the view already, there is no imageview on viewdidDisappear event.
In brief, my question is that am i using right method to achieve this? If so, how can i successfully release all child view controllers?
I finally found a way. I probably found the error. What i have done is cutting the branch on which i am sitting. I was releasing the view controller which i am currently in:) When viewdidDisappear called, there is no such view controller. Because i throw away it to space already.Below is my working steps. I hope it will be useful to someone. But i cant stand thinking of apple may reject my app. I wish finding a suitable way.
This is my working ultimate way of using split view controller and navigation controller as window root view controller alternately.
Firstly i defined NavigationController and SplitViewController property in AppDelegate interface.
AppDelegate.h
#property (assign,nonatomic) UINavigationController * NC;
#property (assign,nonatomic) UISplitViewController *SVC;
Secondly i assign newly created NC on AppDelegate didFinishLaunch event.
AppDelegate.m
//Creating my main screen controller
//Creating my navigation controller with my view controller instance. Then
self.NC= my_navigation_controller;
self.window.rootViewController= self.NC;
Thirdly creating a splitview controller and setting as app's root view controller
MyMainScreen.m
-(void) OpenSplit()
{
//Creating my master view controller of SVC
//Creating my detail view controller of SVC
//Creating my SVC;
AppDelegate * app_delegate= [[UIApplication sharedApplication] delegate];
app_delegate.SVC= newly created my SVC;
app_delegate.window.rootViewController= app_delegate.SVC;
}
Fourthly releasing unused NC in viewDidLoad event of detail view of SVC.
MyDetailView.m
- (void) viewDidLoad()
{
...
AppDelegate * app_delegate= [[UIApplication sharedApplication] delegate];
app_delegate.NC= nil; //i dont need it now. i am releasing. Releasing Navigation Controller release as well child controllers. I learned with testing.
}
Fifthly managing close split view function.I used UIBarButton on NavigationBar in DetailView.
MyDetailView.m
-(void) closeSplitView
{
//Creating navigation controller with my main screen view controller
AppDelegate * app_delegate= [[UIApplication sharedApplication] delegate];
app_delegate.NC= newly_created_NC;
app_delegate.window.rootViewController= appdelegate.NC;
}
Sixthly handling unused split view controller in Main Screen viewDidLoad event.
MyMainScreen.m
-(void) viewDidLoad
{
AppDelegate * app_delegate= [[UIApplication sharedApplication] delegate];
app_delegate.SVC= nil; //I am releasing it because i am working with NC now.
}
How do I access the tab bar view controller from app globals? The tab bar view controller is set up in storyboard. I dont want to create a new one but get the existing one.
I guess the UITabBarViewController is set as the app's window rootviewController. If that's the case , you can get it like this:
AppDelegate *myAppDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate];
UITabBarViewController *myTabBarViewController = (UITabBarViewController *) myAppDelegate.window.rootViewController;
, where AppDelegate is the name of your App Delegate class.
Hope this helps.
Regards,
George
I'm trying to switch tabs programmatically using:
[tabBarController setSelectedIndex:index]
I've also tried:
tabBarController.selectedViewController = [tabBarController.viewControllers objectAtIndex:index];
It works the first time - switching both tabs and the view associated with the tab. However it doesn't work the second time and thereafter. Then it erratically switches the tab (not always), and doesn't switch the view controller associated with the tab.
Any ideas?
Here's what I'm trying to accomplish:
Tab A: I have a tab that launches the camera to take a picture and add some details.
Tab B: I have a tab with a list of pictures taken and a bar button to add a new item by taking a picture and adding details.
I'm trying to make it so that when the user taps Tab A it switches to Tab B and launches the add item method. What's the best way to do this?
Here is more detailed code:
Tab A is hooked up to navigation controller with a UIViewController. In that controller I have the following:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate switchView];
}
In AppDelegate.m I have the following:
- (void)switchView
{
tabBarController = (UITabBarController *)self.window.rootViewController;
tabBarController.selectedViewController
= [tabBarController.viewControllers objectAtIndex:3];
}
The UIViewController class has a tabbarController property, so you can simplify things by calling the view controller's parent controller (the tab bar controller) instead of using the app delegate to access the tab bar controller. Calling setSelectedIndex should be fine too. So from inside your view controller:
[self.tabbarController setSelectedIndex:3];
To help with debugging, you could put some NSLogs in relevant places:
NSLog(#"The currently selected tab is: %#",self.tabbarController.selectedIndex);
It turns out the problem was that I was changing the tabBarController index from viewWillAppear instead of viewDidAppear. Must be something to do with the order in which things are loaded.