Access viewcontroller which resides inside a Tab Bar - objective-c

I'm trying to access it in my AppDelegate by doing this
Course *rootController = (Course *)[navigationController tabcontroller];
but it won't work doesnt seem to get the "Course" root controller.
Thanks

It is not clear from your question how you have your views arranged and what you are trying to achieve. Usually a UITabBarController contains an array of root view controllers. Each view controller corresponding to a tab on the tab bar. Any or all of those view controllers could be a UINavigationController which itself can contain a stack of view controllers.
UITabBarController
|-UINavigationController -> [AViewController,.....]
|-UINavigationController -> [AnotherViewController,.....]
|-UINavigationController -> [AndAnotherViewController,.....]
The navigation controllers which in this case would be the root view controller for each tab can be accessed via the UITabBarController viewControllers property:
NSArray *rootViewControllers = [tabBarController viewControllers];
So if you want the root view controller of the first tab bar:
UINavigationController *rootViewController = [rootViewControllers objectAtIndex:0];

Related

How to access Tab View Controller from another View Controller

I'm having trouble accessing my view controllers under the tab bar controller. Here is what my storyboard looks like:
View Controller A (-> Page View Controller -> View Controller C
View Controller A -> Tab Bar Controller (MyTabBarController.h/.m) -> Navigation Controller (MyNavigationController.h/.m)-> View Controller B (TabViewController.h/.m)
Tab Bar Controller (MyTabBarController.h/.m) -> View Controller D
Tab Bar Controller (MyTabBarController.h/.m) -> View Controller E
From View Controller A I have an IBAction called loginButton that is connected to the Tab Bar Controller, and currently it looks like this:
- (IBAction)loginButton:(id)sender {
MyNavigationController *localNavigationController;
UIStoryboard * storyboard = self.storyboard;
MyTabBarController *tbc = [[MyTabBarController alloc] init];
NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:1];
TabViewController *login = [storyboard instantiateViewControllerWithIdentifier: # "TabViewController"];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:login];
localNavigationController.delegate = self;
[localControllersArray addObject:localNavigationController];
tbc.viewControllers = localControllersArray;
tbc.delegate = self;
tbc.moreNavigationController.delegate = self;
tbc.selectedIndex = 0;
[self presentViewController:tbc animated:YES completion:^{
}];
}
I'm not able to get this displayed correctly. I am getting a bunch of warnings in this piece of code. and it is also not showing the different tab items in the bottom of the Tab Bar, even though I have put images/text on each tab.
So how do I display/access the view controllers inside the Tab Bar Controller correctly? (ie View Controllers C/D/E)?
The storyboard that you show in your question already contains the tab bar controller, navigation controller, and login controller properly hooked up to each other. Because of that, you shouldn't be instantiating a new tab bar controller or navigation controller in code -- they will be instantiated by the storyboard when you instantiate the tab bar controller. So, the only thing you need to do, is to give the tab bar controller in the storyboard an identifier, and do this (assume the identifier is called MyTabBarController):
- (IBAction)loginButton:(id)sender {
UITabBarController *tbc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyTabBarController"];
[self presentViewController:tbc animated:YES completion:nil];
}
You wouldn't even need this code if you control drag from the "Login" button to the tab bar controller, and choose "Modal". That will create a modal segue which will present the tab bar controller with no code at all.
If you just want to select another tab from the tabBar controller then use something like this:
UITabBarController *tabBar = (UITabBarController *)self.window.rootViewController;
[tabBar setSelectedIndex:3];
Note that if the tabBar controller is the initial view controller you can grab an instance of it it the applicationDidFinishLaunching method and store it in the AppDelegate. Then you'll be able to access it like this:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
Remember to import the AppDelegate.h
I recommand you to use a Singleton shared instance to share multiple informations form multiple controllers.
It's a good design Pattern for you usage.
I'm writing samples of Design Patterns usage on cocoa (see https://github.com/leverdeterre/DesignPatterns -> Real singleton)

Detect rootcontroller in iphone sdk

I have using two types of controller in my application i.e. NavigationController and presentViewController.
How can I detect base controller at any instance through code i.e I am using navigation or presentviewcontroller to transist one viewcontroller to another viewcontroller?
Try this for take rootviewcontroller of navigation:
UIViewController *topViewController = [self.navigationController topViewController];
for present modal view controller check out the 'presentingViewController' property of UIViewController and for navigation you can get the array of view controllers NSArray *ArryViewControllers=[self.navigationController viewControllers]; and then get the object at index 0 . this will be the root view controller of that navigation controller.

Changing master view and detail view from uisplitview

On my storyboard, my project begins with a split view that automatically assigns my custom UITableViewController (embedded in a navigation controller) as the detail view controller (done by relationship segue). How do I access the split view controls from my custom UITableViewController so I can change the master view controller views as appropriate?
UIViewController has a property splitViewController that is a reference to the split view controller the viewController is embedded inside. Since your table view controller is embedded inside a navigation controller, which is itself embedded inside a split view controller, you first need to get a reference to the nav controller, and then from that get its reference to the split view.
So in your custom tableViewController's code you can do this:
UISplitViewController *splitVC = [[self navigationController] splitViewController];
The from that you can get a reference to your masterViewController. The splitViewController has a property viewControllers which is an NSArray of two elements. The element at index zero is the master viewController. The element at index 1 is your detail view controller.
UIViewController *masterVC = [[splitVC viewControllers] objectAtIndex:0];
Note that if your master is a custom viewController subclass (which it probably is) you should cast it as such when you pull it out of the array.
If you want to relace the master view controller with a new viewController entirely, you can do that by creating a new array with your new master VC and the existing detail view controller and assigning it to your split view controller's viewControllers property:
UIViewController *detailVC = [[splitVC viewControllers] objectAtIndex:1];
NSArray *newViewControllerArray = [NSArray arrayWithObjects:newMasterVC, detailVC, nil];
splitVC.viewControllers = newViewControllerArray;

Add a XIB view to a tab view in the storyboard

I am working on an Iphone application.
I am using a StoryBoard.
I have a Tab View with 3 tabs. "Home", "Users" and "Settings".
I create the "Home" and "Users" view on the story board, but The settings view is a XIB file (SettingsView.xib)
How can I make the third tab ("Settings") open the SettingsView.xib? Can I use both the story board and xib files?
I tried to initialize a UINavigationController in the startApp method in the AppDelegate but I can't find out how to add it to the story board.
Thanks for any help
TabViewControllers usually have one navigation controller for each tab.
Create the navigation controllers in storyboard and connect them to the navigationcontrollers relation of the tab view controller.
The initial view of the navigation controller connects to the rootViewController relationship of the navigation controller.
As to your second question, I'm not certain, but I think the following will work:-
Create a UIViewController in storyboard and change it's class to your class that you're loading from an XIB. When the storyboard instantiates the class, it will use the XIB provided the class name of the class exactly matches the name of the XIB. I don't think you can do any iPad/iPod checking here though.
You can add a xib-based view to your storyboard-based tab bar controller as follows. I am assuming the following:
The tab bar controller is the initial view controller of your storyboard.
Your settings controller is a class called SettingsController
You have a tab bar image in your bundle called SettingsTabImage
Define the tab bar controller in the storyboard with just your storyboard-based tab bar items in it - Home and Users in your case
In your application delegate, use the following code in application:didFinishLaunchingWithOptions::
// Create your settings view controller
SettingsController *settingsVC = [[SettingsController alloc] initWithNibName:nil bundle:nil];
// Create a tab bar item
UITabBarItem *settingsItem = [[UITabBarItem alloc] initWithTitle:#"Settings" image:[UIImage imageNamed:#"SettingsTabImage" tag:0];
settingsVC.tabBarItem = settingsItem;
// Get a reference to the tab bar controller
UITabBarController *tbC = (UITabBarController*)self.window.rootViewController;
// Get the current view controllers in your tab bar
NSMutableArray *currentItems = [NSMutableArray arrayWithArray:tbC.viewControllers];
// Add your settings controller
[currentItems addObject:settingsVC];
tbC.viewControllers = [NSArray arrayWithArray:currentItems];

Tab bar controller not appearing correctly

I'm trying to connect Tab Bar Controller to existing part of my app, but when I do that it's "malfunctioning".
However when I run Tab Bar Controller part standalone as initial view controller it works properly like in the image below :
This is how app looks when it is run(correct behavior) :
However when I go to this tab bar controller from my main app this is how it looks like this:
My main app looks like this :
Scroll View contains
UIView 1
UIView 2
UIView 3
UIView x
Each view does something not related to this tab bar controller. Only one view view x tries to "visit" tab bar controller and display some data there, but it's not. Any ideas?
I have this tab bar controller identifier set to test, and I here is how I do that from my view x :
UITabBarController *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"test"];
[self.view addSubview:newViewController.view];
EDIT :
Entire app :
I'm creating views programatically. That's why I don't have any relationships/segues to the tab bar controller.
SOLUTION :
Change :
UITabBarController *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"test"];
[self.view addSubview:newViewController.view];
To :
UITabBarController *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"test"];
[self addChildViewController:newViewController];
[self.view addSubview:newViewController.view];
You need to set a root viewController to the navigation Controller
Just don't do this. From the Apple UITabBarController referenece
Because the UITabBarController class inherits from the UIViewController class, tab bar controllers have their own view that is accessible through the view property. When deploying a tab bar interface, you must install this view as the root of your window. Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.
As I understand it means you must use UITabBarController only as a root view controller of the window. But you can alway use a general UIViewController and add UITabBar there.
(The view offset problem you've met is possible to be fixed, it will not follow the Apple guidelines however and not advised).