I would like to place two UIViewControllers on a window (like you can see below). Is it possible to set this up to each view is controlled by it's own controller respectively?
In the app delegate I'm adding the subview the following way
TabBarViewController *tabBarVC = [[TabBarViewController alloc] init];
CGRect frame = tabBarVC.view.frame;
frame.origin.y = self.window.bounds.size.height - frame.size.height;
tabBarVC.view.frame = frame;
[self.window insertSubview:tabBarVC.view aboveSubview:tabVC.view];
It loads, but when I click on a button (IBAction), or do anything which needs the controller, the app crashes. What am I doing wrong?
Thanks!
Create a strong reference for an iVar or property for tabBarVC and change this line:
TabBarViewController *tabBarVC = [[TabBarViewController alloc] init];
To:
tabBarVC = [[TabBarViewController alloc] init];
Or
self.tabBarVC = [[TabBarViewController alloc] init];
Yes you can..! have the controllers you want to display as iVars of the view controller you want to display in. Then just use,
[MainController addSubview:desiredConroller1.view];
[MainController addSubview:desiredConroller2.view];
You can load the controller from the storyboard using,
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"storyboard_name" bundle:nil];
desiredController1 = [membershipStoryboard instantiateInitialViewController];
you can also use instantiateViewControllerWithIdentifier:
Related
I think the title of the question may be misleading as I'm not quite sure how to word this in a line.
I'm trying to implement a reveal controller (like those seen in the Facebook app), and I'm using a sweet pre-made solution SWRevealViewController which can be found here.
In one of the most simple examples the author provides (Example/project 2), in the Appdelegate.m file the reveal controller stuff is established:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window = window;
FrontViewController *frontViewController = [[FrontViewController alloc] init];
RearViewController *rearViewController = [[RearViewController alloc] init];
UINavigationController *frontNavigationController = [[UINavigationController alloc] initWithRootViewController:frontViewController];
UINavigationController *rearNavigationController = [[UINavigationController alloc] initWithRootViewController:rearViewController];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:rearNavigationController frontViewController:frontNavigationController];
mainRevealController.delegate = self;
self.viewController = mainRevealController;
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Where viewcontroller is defined in the appdelegate.h file by
#property (strong, nonatomic) SWRevealViewController *viewController;
So this displays the reveal controller as the root view controller. For my app, my root view controller is different and I only start using the reveal controller later in the app. My root view controller is the login screen, and then the proceeding view is where I want to implement this.
I guess my questions are:
Firstly, is it correct to put the login screen as the root view controller? Should I be using some sort of modal view to pop this up then get rid of it?
How and where would I go about putting the stuff previously found in the delegate files? Or do they remain there but are not assigned to the root view controller?
I feel really in the dark about this, so forgive me if it seems completely trivial.
Thanks!
I have thought about this problem recently. In fact all other third party implementations I found all have this setup.
My recommendation is to change the root controller to the reveal controller and build everything up from there. You can disable reveal for your original root, login or any other controller. I did it once and it was not as painful as anticipated.
I am late to the party, the behavior you want is easy to implement, just think about it as a normal navigation stack. Let's take the example 2 which you were following along the way (you don't need to move the code out of the delegate). Instead of setting the front view controller as the root of the front navigation controller, you should set the login view controller as the root of the front navigation controller.
Here is the example before:
FrontViewController *frontViewController = [[FrontViewController alloc] init];
RearViewController *rearViewController = [[RearViewController alloc] init];
UINavigationController *frontNavigationController = [[UINavigationController alloc] initWithRootViewController:frontViewController];
UINavigationController *rearNavigationController = [[UINavigationController alloc] initWithRootViewController:rearViewController];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:rearNavigationController frontViewController:frontNavigationController];
And here is the example after setting the login view controller:
LoginViewController *loginVC =[[LoginViewController alloc]init];//instead of frontViewController
RearViewController *rearViewController = [[RearViewController alloc] init];
UINavigationController *frontNavigationController = [[UINavigationController alloc] initWithRootViewController:loginVC];//instead of frontViewController
UINavigationController *rearNavigationController = [[UINavigationController alloc] initWithRootViewController:rearViewController];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:rearNavigationController frontViewController:frontNavigationController];
Don't forget to create the LoginViewController or whatever you choose to name with its nib file and to import it.
In LoginViewController, you need to implement the action code to move to the frontviewcontroller:
FrontViewController *frontViewController = [[FrontViewController alloc] init];
[self.navigationController pushViewController:frontViewController animated:YES];
Et voila.
I am an iOS development newbie. I want to go to another page (CountryViewController) from my current page (CityViewController) on the click of a button. How would I do that? Pardon me if this is a very beginner question.
There are several ways. I assume you are using a UINavigationController. If so then you can create the VC and do this inside of your parent view controller.
[self.navigationController pushViewController:viewController animated:YES]
So basically you are trying to build a multi-view app. There are many ways to do so. Bu I'll list 3 common ones -
[self.view insertSubview:newViewController.view atIndex:3];
Using UINavigationController
Finally using modalViewController - [self presentModalViewController:newViewController animated:YES];
In second method, I use this controller without UINavigationTabBar. Hide this navigationBar & provide custom buttons based on which [self.navigationController popViewControllerAnimated] should occur.
ViewController2 *newView = [self.storyboard instantiateViewControllerWithIdentifier:#"viewController"];
[self.navigationController pushViewController:newView animated:YES];
set storyboard id in ViewController2 "Identity inspector".
I have came across the same problem. While User logged in once need to redirect to different page or else need to stay in homepage by default.
Here is the code snippet.
Here
N_loginmsg = #"success";
NSString *N_loginmsg = [[NSUserDefaults standardUserDefaults]objectForKey:#"remember_loginmsg"];
NSString *storyboardId;
if (N_loginmsg != nil && [N_loginmsg isEqual:#"Success"])
{
storyboardId = #"ListViewController";
}
else
{
storyboardId = #"HomeViewController";
}
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:storyboardId];
UINavigationController *mynav = [[UINavigationController alloc]initWithRootViewController:initViewController];
self.window.rootViewController = mynav;
[self.window makeKeyAndVisible];
I've been stuck trying to puzzle this out for a couple days now, and I'll admit I need help.
The root view controller of my application is a tab bar controller. I want to have each tab bar a different navigation controller. These navigation controllers have completely different behavior.
So how do I set this up in terms of classes? Per Apple's documentation, I'm not supposed to subclass UINavigationViewController. So where do I put the code that drives each of these navigation controllers? Does it all get thrown in App Delegate? That would create an impossible mess.
This app should run on iOS 4.0 or later. (Realistically, I can probably require iOS 4.2.)
This is taken from one of my applications. As you say, you are not supposed to subclass UINavigationController, instead you use them as they are and you add viewcontroller on the UINavigationController's. Then after setting the root viewcontroller in each UINavigationController, you add the UINavigationController to the UITabBarController (phew!).
So each tab will "point" to a UINavigationController which has a regular viewcontroller as root viewcontroller, and it is the root viewcontroller (the one you add) that will be shown when a tab is pressed with a (optional) navigationbar at top.
UITabBarController *tvc = [[UITabBarController alloc] init];
self.tabBarController = tvc;
[tvc release];
// Instantiates three view-controllers which will be attached to the tabbar.
// Each view-controller is attached as rootviewcontroller in a navigationcontroller.
MainScreenViewController *vc1 = [[MainScreenViewController alloc] init];
PracticalMainViewController *vc2 = [[PracticalMainViewController alloc] init];
ExerciseViewController *vc3 = [[ExerciseViewController alloc] init];
UINavigationController *nvc1 = [[UINavigationController alloc] initWithRootViewController:vc1];
UINavigationController *nvc2 = [[UINavigationController alloc] initWithRootViewController:vc2];
UINavigationController *nvc3 = [[UINavigationController alloc] initWithRootViewController:vc3];
[vc1 release];
[vc2 release];
[vc3 release];
nvc1.navigationBar.barStyle = UIBarStyleBlack;
nvc2.navigationBar.barStyle = UIBarStyleBlack;
nvc3.navigationBar.barStyle = UIBarStyleBlack;
NSArray *controllers = [[NSArray alloc] initWithObjects:nvc1, nvc2, nvc3, nil];
[nvc1 release];
[nvc2 release];
[nvc3 release];
self.tabBarController.viewControllers = controllers;
[controllers release];
This is how I go from one viewcontroller to another one (this is done by tapping a cell in a tableview but as you see the pushViewController method can be used wherever you want).
(this is taken from another part of the app)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.detailedAnswerViewController == nil) {
TestAnsweredViewController *vc = [[TestAnsweredViewController alloc] init];
self.detailedAnswerViewController = vc;
[vc release];
}
[self.navigationController pushViewController:self.detailedAnswerViewController animated:YES];
}
The self.navigationcontroller property is of course set on each viewcontroller which are pushed on the UINavigationController hierachy.
I am editing my question that i had programetically add the tabbar as shown below:-
FirstViewController *obj_FirstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *obj_SecondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
ThirdViewController *obj_ThirdViewController = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
navigation1 = [[UINavigationController alloc] initWithRootViewController:obj_FirstViewController];
navigation2 = [[UINavigationController alloc] initWithRootViewController:obj_SecondViewController];
navigation3 = [[UINavigationController alloc] initWithRootViewController:obj_ThirdViewController];
MainTabBar = [[UITabBarController alloc] init];
MainTabBar.delegate=self;
[MainTabBar setViewControllers:[NSArray arrayWithObjects:navigation1,navigation2,navigation3,nil]];
MainTabBar.view.frame=self.view.frame;
MainTabBar.selectedIndex=0;
[self.view addSubview:MainTabBar.view]
By writing this in (void)viewDidLoad i got the 3 tab in my viewcontroller.But the problem is i want to set the name of the tab as
Home
Favorites
About us
I had tried by writing the below code:-
obj_FirstViewController.tabBarItem.title=#"Home";
self.title = #"My View Controller";
But this does not work - can anyone please help me how to do this programatically? Where to write the line so that i get this 3 name in my tab bar
this is how I made it
1) I made a view controller with your tabbar
2) added view controllers for each tab and a method to the tabbar view controller class:
-(void)updateContentsWithViewController:(UIViewController *)insideViewController
the method is called when a tabbutton is pressed.
3) here is the code for the switching
- (void)updateContentsWithViewController:(UIViewController *)insideViewController {
//internalViewController is the viewController which you change
[internalViewController.view removeFromSuperview];
[internalViewController release];
internalViewController = [insideViewController retain];
navController = [[UINavigationController alloc] initWithRootViewController:insideViewController];
[navController setNavigationBarHidden:YES];
[navController.view setFrame:CGRectMake(0, 0, 320, 348)];
//frame I needed in my app .. can be changed
[self.internalView addSubview: navController.view];
//navController is the property for the navigationController
[self.view sendSubviewToBack: self.internalView];
}
its possible add tabBar in separate view controller which will be like rootview controller ,then in viewDidLoad of the root view controller assign the object of tabbar created to a appdelegate tabBar declared ...then use appdelegate tabbar for other navigation's alone .
I am having a problem with the following code:
MyViewController *aController = [[MyViewController alloc] initWithNibName:#"MyView" bundle:nil];
self.myController = aController;
myController.title = #"List";
[aController release];
UINavigationController *bController = [[UINavigationController alloc] initWithRootViewController:myController];
self.rootNavController = bController;
[bController release];
[self.view addSubview:rootNavController.view];
When I run my program I get the problem where my view for myController is repeated along the y-axis all the way until the bottom of the screen. If I add myController.view to the root view it works ok. I only have the problem when I add myController as the rootViewController of my navigation controller.
Thanks in advance for any help!
The default navigation controller project template defines -applicationDidFinishLaunching this way:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
I realize you're instantiating your nav controller with alloc init rather than getting it from the XIB, however, it seems you ought to be adding it to the window's view tree.
Where is the code you are showing being called from?
The problem was that I did not specify the frame. Without specifying a frame using CGRectMake the view controller was just filling the entire space.
The line I needed was something like this:
rootNavController.view.frame = CGRectMake(0, 0, 320, 431);
Try this:
MyViewController *aController = [[MyViewController alloc] initWithNibName:#"MyView" bundle:nil];
self.myController = aController;
[aController release];
UINavigationController *bController = [[UINavigationController alloc] initWithRootViewController:myController];
self.rootNavController = bController;
[bController release];
[window addSubview:rootNavController.view];//<--What are you adding the navigationController to??? Another ViewController? TabController? or Window?
Then in the -(void)viewDidLoad method of MyViewController you can put
self.navigationItem.title = #"List";