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.
Related
i have a tabBarController application and using .xib files for the interface not the storyboard
i have this code by default in the appdelegate
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[PopAdsFirstViewController alloc] initWithNibName:#"PopAdsFirstViewController" bundle:nil];
UIViewController *viewController2 = [[PopAdsSecondViewController alloc] initWithNibName:#"PopAdsSecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
i have created a Login View and don't know how to show it before the tabBarView and hide t after a successful login.
One way would be to show it as a modalView on launch. Dismissing upon successfull login?
eg:
UIViewController myLoginViewController = [[MyLoginViewController alloc] init withNibNamed:"MyLoginViewController"]; //Or whatever you instantiation is
[myTabViewController presentModalViewController:myLoginViewController animated:YES];
And to dismiss it (Hide it)
//This should be done from the original View Controller i.e. myTabViewController preferably in a delegate called by the modal view controller.
[self dismissModalViewControllerAnimated:YES];
Documentation on modalViewControllers:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
The way that I did it for one of my apps is to just add them in the correct order. Add your tabbar controller to your window, then add the login controller over the top of the tab bar. Then show your window. The user won't see anything but your login controller. Once you login, you can just remove the login controller from view.
This way is probably best if you have information you need to hide until login. The other way is to only launch the login view only. On successful login, remove the login and add the tab bar controller. Either way is fine.
Presenting modally is probably the easiest, but requires a view in place before presenting. So if the data and view under the login controller isn't that sensitive, you could consider this option.
Another way would be using LoginViewControllerDelegate in your appDelegate.h file
In your .h
#import "yourLoginViewController"
//and add LoginViewControllerDelegate
Then in your .m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
yourLoginViewController *loginView = [[yourLoginViewController alloc] initWithNibName:#"yourLoginViewController" bundle:nil];
loginView.delegate = self;
[window addSubview:loginView.view];
[window makeKeyAndVisible];
}
//add this one
- (void)loginViewControllerDidFinish:(yourLoginViewController *)loginViewController {
[window addSubview:tabBarController.view];
}
I have 3 tabs and main navigation controller. I implements with code:
UIViewController *monitorController = [[[MonitorController alloc] initWithNibName:#"MonitorController" bundle:nil] autorelease];
UIViewController *dashboardController = [[[DashboardController alloc] initWithNibName:#"DashboardController" bundle:nil] autorelease];
UIViewController *settingsController = [[[SettingsController alloc] initWithNibName:#"SettingsController" bundle:nil] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:monitorController, dashboardController, settingsController, nil];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:self.tabBarController] autorelease];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
I want to change navigation title when I select another tap, but no variant (see below) not working (there are no any title at navigation controller):
self.title = DASHBOARD_TITLE;
self.navigationController.title = DASHBOARD_TITLE;
How I can resolve this problem?
The UINavigationController will display the title of the UIViewController it's currently displaying, that is why you are not able to set it directly.
You may try to change the title on your UITabBarController, but I'm not sure the navigation controller will update it's title after it first appeared on screen.
But, Do you really need that Architecture?
Usually the UITabBarController is the root viewController and if you need UINavigationControllers they are place inside the Tab that need to have navigation capability.
It was design to be use that way.
Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.
Quoted from UITabBarController Class Reference
Sorry I misread your question, what you have to do is to implement -tabBar:didSelectItem: from UITabBarDelegate protocol, and then change the title according to the pressed tab.
Or in the ViewWillAppear method of your controllers set the title, the way you were doing it
Hihi all,
I am pretty new in iPhone dev. I have follow some tutorial and created a tabbar application. Below is the code in the appdelegate implementation:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController *viewController1 = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil];
UIViewController *viewController2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
Then set the title and the image for the tab in each of the controller implementation.
My problem is that, example, in my viewController1, I need to navigate to viewController3, when I use presentModalViewController method to push the viewController3 in, the tabbar at the bottom will be disappeared.
While I tried to use the app delegate to refer to my tabBarController, and use tabBarController.navigationController pushViewController method, my viewController3 is not being pushed, and seems nothing happens.
I have tried to follow a few tutorial, but it's all required to drag in the navigationcontroller into the MainWindow.xib, which, in the xcode 4, MainWindow.xib doesn't exist anymore. How can i create the navigationcontroller from code so that the app can navigate between different view without hiding the tabbar?
Any comment is very much appreciated! Thanks in advance!
:)
If you want to use a navigation controller, you need to create a navigation controller. Since you're not using a XIB, you'll have to create it manually.
Since you want the tab bar to remain visible when you present viewController3, you need to make the navigation controller a child of the tab bar controller.
UIViewController *viewController1 = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil];
UINavigationController *navController1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
UIViewController *viewController2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:
navController1,
viewController2,
nil];
Then when you want to present viewController3, do this:
// in some method of viewController1
[self.navigationController pushViewController:viewController3 animated:YES];
I am not very Sure but have you tried this??? Actually i am going to use XCode 4 soon, i am still using 3.2.8 version:-
WebViewController *viewController = [[WebViewController alloc]initWithNibName:#"WebViewController" bundle:nil];
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
[viewController release];
See in this also the Tab bar will be removed when you navigate to your 3rd screen, you have to provide the navigation bar to come back.
Hope it helps.. :)
My UITabBar is not completely showing after I present a UITabBarController from a UIViewController. Please can you tell me what I am doing wrong?
My code is:
//some method
LoggedInViewController *lvc = [[[LoggedInViewController alloc] initWithAccount:account] autorelease];
[self presentModalViewController:lvc animated:YES];
- (void)viewDidLoad
{
self.tabController = [[UITabBarController alloc] init];
LoggedInFeedNavigationController *navController = [[LoggedInFeedNavigationController alloc] initWithAccount:self.account];
[self.tabController setViewControllers:[NSArray arrayWithObject:navController]];
[self.view addSubview:self.tabController.view];
[super viewDidLoad];
}
It's not a good practice to do:
[viewController1.view addSubview:viewController2.view];
The point of the MVC design is lost. The view controller should get your data (from the model) and put it in the view. If you have more than one view just arrange the functionality of the views to accept the corresponding data.
So if you need a tab bar controller you should do the following:
// assuming you are in the same initial controller
UITabBarController* pTabBarControllerL = [[UITabBarController alloc] init];
MyFirstController* pFirstControllerL = [[MyFirstController alloc] init];
[pTabBarControllerL setViewControllers:[NSArray arrayWithObject:pFirstControllerL]];
// perhaps set more tab bar controller properties - button images and so on
[self presentModalViewController:pTabBarControllerL animated:YES];
// release the memory you do not need
-(void)viewDidLoad {
// do your work in pFirstControllerL
}
PS: You should not subclass UINavigationController and UITabBarController.
Actually according to the Apple's recommendations UITabBarViewController should be the root in the UIWindow hierarchy. We had hard times trying to put TabBar VCs or Navigation VCs not to the root.
I have been working on a UINavigationController based application, using a UITableView for the rootview and Core Data for the data source.
Unfortunately I didn't plan ahead very well and now would like to implement tab bar navigation to the app on top of what I already have.
Can anyone recommend a simple way to do this? Or am I better off starting again with the TabBar based template and try to plugin my existing code?
Thanks guys!
Adam
Rather than start over, you may just want to create a tab-bar-based app and look at the code it produces, then try to do the same thing in your app.
You probably just need to change your application delegate's application:didFinishLaunchingWithOptions: method to look something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSMutableArray *viewControllers = [[[NSMutableArray alloc] init] autorelease];
// First tab
MyController *myController = [[[MyController alloc] init] autorelease];
mapViewController.navigationItem.title = #"First";
UINavigationController *myRootController = [[[UINavigationController alloc]
initWithRootViewController:myController]
autorelease];
myRootController.tabBarItem.title = #"First";
myRootController.tabBarItem.image = [UIImage imageNamed:#"MyControllerTab"];
[viewControllers addObject:myRootController];
// Second tab
MyOtherController *myOtherController = [[[MyOtherController alloc] init] autorelease];
myOtherController.navigationItem.title = #"Second";
UINavigationController *otherRootController = [[[UINavigationController alloc] initWithRootViewController:myOtherController] autorelease];
otherRootController.tabBarItem.title = #"Second";
otherRootController.tabBarItem.image = [UIImage imageNamed:#"OtherControllerTab"];
[viewControllers addObject:otherRootController];
// Create other tabs
// ...
// Tab bar
UITabBarController *tabBarController = [[[UITabBarController alloc] init] autorelease];
[tabBarController setViewControllers:viewControllers];
[self.window setRootViewController:tabBarController];
[self.window makeKeyAndVisible];
return YES;
}
If you want to plug in your existing navigation controller to one of the tabs on a tab bar, it's pretty simple - just define a new UITabBarController to serve as the root controller and have it load your navigation controller into a single tab. Then change your app delegate to load the tab bar controller instead of your navigation controller.
If, however, you want to pull out multiple controllers from your existing navigation stack, you might have to do a bit more work - find places where you call pushViewController:animated: to modify your navigation stack, and instead plug those view controller instances into tabs on your tab bar. Here's where it might be worthwhile to start from a fresh tab bar template and copy over existing controllers, depending on the complexity of your code.
Adam,
Not sure how much coding you've done already, but if you're not that familiar with connecting things in IB and setting delegates you might be better off starting over with a TabBarController template.
Here's what you do:
Define new IBOutlet for UITabBarController in AppDelegate and Add TabBarController to IB
Connect UITabBarController to IBOutlet in AppDelegate in IB
Set Delegate for UITabBarController in IB to AppDelegate
Change rootViewController to tabBarController in AppDelegate
Drag All ViewControllers into Tab Bar Controller in IB
Setup other Tabs using NavigationControllers or UIViewControllers depending on your design
Run, Fix, Repeat