UITabBarController + UISplitviewController alternatives? - iphone

As this configuration is not supported I was wondering what alternatives people have used.
I have a universal app which currently uses a 4 tab UITabBarController on both the iPhone and iPad.
As I'd now like to use the splitviewcontroller I am faced with a design decision.
I guess I could just go with a toolbar at the top and go from there but was hoping there were more interesting techniques.

You could replicate a UITabBar within a modelViewController that pops up when a button on the bottom of the screen is taped and swap Views. :)

I created a UITabBarController subclass which properly propagates the rotation messages to all UISplitViewControllers it contains. This maintains the correct internal state of the UISplitViewControllers. However, one of the SplitViewController delegate methods is not called if the SplitViewController is not visible, so I account for this in the detail view controller viewWillAppear method. I've confirmed this works in iOS5.0 - iOS6.1
AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
OSMasterViewController *masterViewController = [[[OSMasterViewController alloc] initWithNibName:#"OSMasterViewController_iPhone" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
self.window.rootViewController = self.navigationController;
} else {
OSMasterViewController *masterViewController = [[[OSMasterViewController alloc] initWithNibName:#"OSMasterViewController_iPad" bundle:nil] autorelease];
UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
OSDetailViewController *detailViewController = [[[OSDetailViewController alloc] initWithNibName:#"OSDetailViewController_iPad" bundle:nil] autorelease];
UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
masterViewController.detailViewController = detailViewController;
UISplitViewController *splitViewController = [[[OSSplitViewController alloc] init] autorelease];
splitViewController.viewControllers = #[masterNavigationController, detailNavigationController];
splitViewController.delegate = detailViewController;
OSTestViewController *secondaryController = [[[OSTestViewController alloc] init] autorelease];
OSTabBarController *tabBarController = [[[OSTabBarController alloc] init] autorelease];
tabBarController.viewControllers = #[self.splitViewController, secondaryController];
self.window.rootViewController = tabBarController;
}
[self.window makeKeyAndVisible];
return YES;
}
OSTabBarController.m
#import "OSTabBarController.h"
#implementation OSTabBarController
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
for(UIViewController *targetController in self.viewControllers){
if(targetController != self.selectedViewController && [targetController isKindOfClass:[UISplitViewController class]]){
[targetController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
}
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
for(UIViewController *targetController in self.viewControllers){
if(targetController != self.selectedViewController && [targetController isKindOfClass:[UISplitViewController class]]){
[targetController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
}
}
#end
DetailViewController
#implementation OSDetailViewController
-(void)viewWillAppear:(BOOL)animated{
//the splitViewController:willHideViewController:withBarButtonItem:forPopoverController: may not have been called
if(!UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
self.navigationItem.leftBarButtonItem = nil;
}
}
#pragma mark - UISplitViewControllerDelegate Methods
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
}
#end

Related

how to change the rootviewcontroller

I want to change the rootViewController after the authenticationViewController
-(IBAction)LoginButtonPushed:(id)sender {
if ([(VerifyId)isEqual:#"C"]){
CondidatsViewController *condidatsViewController = [[[CondidatsViewController alloc]initWithNibName:#"CondidatsViewController" bundle:nil]autorelease];
UINavigationController *navController = self.navigationController;
NSMutableArray *controllers = [[self.navigationController.viewControllers mutableCopy] autorelease];
[controllers removeLastObject];
navController.viewControllers = controllers;
[navController pushViewController:condidatsViewController animated: YES];
} else {
RecruteursViewController *recruteursViewController = [[[RecruteursViewController alloc]initWithNibName:#"RecruteursViewController" bundle:nil]autorelease];
UINavigationController *navController = self.navigationController;
NSMutableArray *controllers = [[self.navigationController.viewControllers mutableCopy] autorelease];
[controllers removeLastObject];
navController.viewControllers = controllers;
[navController pushViewController:recruteursViewController animated: YES];
}
}
this code is when i press in login button i want CondidatsViewController or RecruteursViewController will be the rootView
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
AcceuilViewController *viewController =[[[AcceuilViewController alloc]
initWithNibName:#"AcceuilViewController" bundle:nil]autorelease];
self.navController = [[[UINavigationController alloc]initWithRootViewController:viewController]
autorelease];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
return YES;
}
You can try UINavigationController's following method with a new array of desired view controllers something like
[self.navigationController setViewControllers:#[newRootViewControllerInstance, secondVCInstanceIfRequired, thirdVC-and-so-on....] animated:NO];
It will do the trick ;)
How about have a view controller one level above your nav and auth view controllers? This view controller can check for a valid session and push whatever view is appropriate on top of the stack. It seems ill advised to try to change your root view controller.
Edit: More details
You have a root view controller that doesn't have a view tied to it like most other view controllers might. You set this class as the root view controller in your app delegate.
App Delegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
RootViewController *rootViewController = [[RootViewController alloc] init];
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
In your root view controller you can determine if you have a valid session or not. Based on that, you can render the appropriate view.
RootViewController.m
#interface RootViewController ()
#end
#implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
BOOL isUserAuthenticated = [MyClasskToFigureOutIfUserIsAuthenticated isUserAuthenticated];
if(isUserAuthenticated == NO) {
AuthViewController *vcAuth = [[AuthViewController alloc] init];
[self addChildViewController:vcAuth];
[self.view addSubView:vcAuth.view];
} else {
//they are authenticated so push your other view controller.
}
}
#end
This is pretty rough, but it should point you in the right direction.

App Crashing using popViewControllerAnimated:YES

I am trying to create a back button to return to the main menu of my app, what is happening now, is, once I press the back button, it shows the main menu, but then the app crashes out a second later.
The code I use for back button is;
- (void)backButtonPressed:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
From the AppDelegate.m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[[MenuViewController alloc] initWithNibName:#"MenuViewController_iPhone" bundle:nil] autorelease];
} else {
self.viewController = [[[MenuViewController alloc] initWithNibName:#"MenuViewController_iPad" bundle:nil] autorelease];
}
navigationController = [[myNavigationViewController alloc] initWithRootViewController:self.viewController];
navigationController.navigationBarHidden = YES;
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
I cannot see where I am going wrong? It seems to call the right screen, yet crashes straight after?
EDIT - Here is MenuViewController.m file;
#import "MenuViewController.h"
#import "MagicAppDelegate.h"
#import "MagicViewController.h"
#interface MenuViewController ()
#end
#implementation MenuViewController
- (void)viewDidLoad
{
self.view.frame = [[UIScreen mainScreen] bounds];
[super viewDidLoad];
// [self initLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)onStart:(id)sender
{
MagicViewController* viewController;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
viewController = [[MagicViewController alloc] initWithNibName:#"MagicViewController_iPhone" bundle:[NSBundle mainBundle]];
else
viewController = [[MagicViewController alloc] initWithNibName:#"MagicViewController_iPad" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
- (void)dealloc {
[super dealloc];
}
#end
Please use below code,do u want go mainmenuview controller.
[self.navigationController popToRootViewControllerAnimated:YES];
Actually, I don't understand your code: In the statement navigationController = [[myNavigationViewController alloc] initWithRootViewController:self.viewController]; you are sending an alloc to something that seems to be the instance of class UINavigationController, but alloc is a class method. I therefore assume myNavigationViewController is a subclass of UINavigationController (but then is should start with a capital letter).
The new instance returned is then assigned directly, i.e. without using a setter method, to variable navigationController. It is therefore not retained. If your statement returns an autorelease object, it will thus be released as soon as the program returns to the main event loop.
Try thus to use thus a setter method, i.e. self.navigationController = [[myNavigationViewController alloc] initWithRootViewController:self.viewController];

Tabbar controller load empty xib

I'm trying to build an app that have main view at the beginning with 3 buttons, then when the user press any button of these buttons, the tab bar view will appear with selected tab bar item.
My problem is here, when the tab bar view should appear ... it appears empty !!
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
MainMenuViewController *mainMenuViewController = [[[MainMenuViewController alloc] initWithNibName:#"MainMenuViewController" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:mainMenuViewController] autorelease];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
//Button Action in main menu view
-
(IBAction)button1Action:(id)sender {
TabbarViewController *tempView = [[TabbarViewController alloc] initWithNibName:#"TabbarViewController" bundle:nil];
[self.navigationController pushViewController:tempView animated:YES];
[tempView release];
}
You have to set viewControllers property of your TabbarViewController(of course if it is superclass of UITabBarController). Create your 3 viewControllers in init method of TabbarViewController, add them to array and set it as viewControllers property like this:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
NSLog(#"%#",[[self class] superclass]);
UIViewController *yourFirstViewController = [[UIViewController alloc] init];
UIViewController *yourSecondViewController = [[UIViewController alloc] init];
UIViewController *yourThirdViewController = [[UIViewController alloc] init];
yourFirstViewController.title = #"First";
yourSecondViewController.title = #"Second";
yourThirdViewController.title = #"Third";
NSArray *threeViewControllers = [[NSArray alloc]initWithObjects:yourFirstViewController, yourSecondViewController, yourThirdViewController, nil];
self.viewControllers = threeViewControllers;
// Custom initialization
}
return self;
}

Navigation pushview Controller is not working

I am implement the TabBar app for ipad & iphone both. But In IPAD the navigation controller is not working for ipad nib in table cell. The viewdid Load method is not call for ipad.
But it work fine for iphone..
self.navigationController is NULL for ipad only in my class to navigate.
Help me!!
my code is as follow:
//Connet.m:
if(i==1)
{
TwitterController *tc;
if ([self isPad]) {
tc = [[TwitterController alloc] initWithNibName:#"TwitterController_ipad" bundle:nil];
}
else
tc = [[TwitterController alloc] initWithNibName:#"TwitterController" bundle:nil];
[self.navigationController pushViewController:tc animated:YES];
NSLog(#"%#",self.navigationController); /Problem ****NULL*****///////
//TWITTER.m
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//Custom initialization
self.navigationController.navigationBarHidden = YES;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = YES;
NSString *urlAddress = #"https://twitter.com/UJUDGEIT1";
//Create a URL object.
NSURL *url = [NSURL URLWithString:urlAddress];
//URL Request Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//Load the request in the UIWebView.
[webv loadRequest:requestObj];
}
Try the following code:
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
NSString *nibname=#"";
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
nibname=#"TwitterController_ipad";
}
else{
nibname=#"TwitterController";
}
TwitterController *view = [[TwitterController alloc] initWithNibName:nibname bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:view];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
Write this code in your app delegate class. The viewDidLoad method gets called.
piyush
how you implement your tab bar.
make each controller of tab bar as navigation controller. it may called your view did load method.
following code may help you. it create 2 controller on tab bar. finally at it to root view controller.
-(void)createTabbar{
NSMutableArray *controllers = [[NSMutableArray alloc] init];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
//Controller 1
PasswordVC *pvc = [[PasswordVC alloc] initWithNibName:#"PasswordVC" bundle:nil];
UINavigationController *passwordNav = [[UINavigationController alloc] initWithRootViewController:pvc];
passwordNav.navigationController.navigationBarHidden=YES;
[controllers addObject:passwordNav];
pvc.title = #"Password";
[pvc release];
[passwordNav release];
//Controller 2
SettingVC *SVC = [[SettingVC alloc] initWithNibName:#"SettingVC" bundle:nil];
UINavigationController *settingNav = [[UINavigationController alloc] initWithRootViewController:SVC];
settingNav.navigationController.navigationBarHidden=YES;
[controllers addObject:settingNav];
SVC.title = #"Settings";
[SVC release];
[settingNav release];
}
else { //ipad
}
_tabBarController = [[[UITabBarController alloc] init] autorelease];
_tabBarController.delegate=self;
_tabBarController.viewControllers = controllers;
_tabBarController.customizableViewControllers = controllers;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:_window cache:NO];
_window.rootViewController = _tabBarController;
[UIView commitAnimations];
}

how to load different xibs in iphone and ipad?

I wanna at certain point of the program to load different xib for iphone and for ipad but wanna to reuse most part of the code. how can I achieve this ?
Append ~ipad or ~iphone to the end of the file name. So SomeViewController~ipad.xib or SomeViewController~iphone.xib for instance.
See iOS Supports Device-Specific Resources.
If you create a template project that is universal you can inspect the code created for that version. For Example:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController_iPhone" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
} else { // iPad
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController_iPad" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
PSGameViewController *detailViewController = [[PSGameViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
}
[self.window makeKeyAndVisible];
return YES;
}
or from tableView:didSelectRowAtIndexPath:
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if (self.detailViewController == nil) {
self.detailViewController = [[PSGameViewController alloc] initWithNibName:#"PSGameViewController_iPhone" bundle:nil];
}
self.detailViewController.model = selectedModel;
[self.navigationController pushViewController:self.detailViewController animated:YES];
self.pushedIndexPath = indexPath;
} else { // iPad
self.detailViewController.model = selectedModel;
}