From what I have read on the internet, nibs and storyboards are comparable with each other in the same project. Now I am creating a tabbed application and would like to do the following:
Tab 1: constructed with nibs,
Tab 2: constructed with storyboards,
Tab 3: constructed with nibs
Initially I created everything with nibs so in my delegate I was passing from one tab to the next with this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1, *viewController2, *viewController3;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPhone" bundle:nil] autorelease];
viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController_iPhone" bundle:nil] autorelease];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPhone" bundle:nil] autorelease];
} else {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPad" bundle:nil] autorelease];
viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController_iPad" bundle:nil] autorelease];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPad" bundle:nil] autorelease];
}
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[viewController1, viewController2, viewController3];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Instead of having the SecondViewController_.xib I need to have the SecondViewController_.storyboard. How do I do this? Can I just change the name "SecondViewController_.nib" to "SecondViewController_.storyboard"? I don't think this would work..
Any help would be very appreciated!!
EDIT:
the code i was using :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Events", #"Events");
self.tabBarItem.image = [UIImage imageNamed:#"second"];
}
return self; }
You could do what you're suggesting by creating a storyboard and then creating a SecondViewController scene inside it. In code, you would then replace initWithNibName: with calls to storyboardWithName: and instantiateViewControllerWithIdentifier:.
However, since a major feature in storyboards is the ability to tie multiple controllers together and define relationships between them, it's hard to imagine why doing it for one controller would be a good idea.
As Phillip said, just use instantiateViewControllerWithIdentifier.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1, *viewController2, *viewController3;
UIStoryboard *storyboard;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPhone" bundle:nil] autorelease];
storyboard = [UIStoryboard storyboardWithName:#"iPhone" bundle:nil];
viewController2 = [storyboard instantiateViewControllerWithIdentifier:#"Second"];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPhone" bundle:nil] autorelease];
} else {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPad" bundle:nil] autorelease];
storyboard = [UIStoryboard storyboardWithName:#"iPad" bundle:nil];
viewController2 = [storyboard instantiateViewControllerWithIdentifier:#"Second"];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPad" bundle:nil] autorelease];
}
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[viewController1, viewController2, viewController3];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
This assumes that your storyboards were called iPhone.storyboard and iPad.storyboard, but change the above code to match whatever you call these two storyboards. Furthermore, this again assumes that you defined that scene to bear a "Storyboard ID" of Second (you do that by selecting the view controller in IB and going to the "Identity Inspector") and also that you specified your "custom class" there, too:
For SecondViewController, you should replace you initWithNibName:bundle: method with:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.title = NSLocalizedString(#"Events", #"Events");
self.tabBarItem.image = [UIImage imageNamed:#"second"];
}
return self;
}
Related
didSelectRowAtIndexPath: is firing but the view controller is not. I have tried different view controllers that I know are working. Since the method is firing then I can only speculate that
[self.navigationController pushViewController:detailVC animated:YES];
is not reaching the navigation stack.
But I call the Calendar View Controller from a tabbarcontroller so I do not know what to do to fix this.
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound)];
GlobalSingleton *myAppID = [GlobalSingleton sharedSingleton];
myAppID.globalAppID = #"627";
UIViewController *calendarVC;
calendarVC = [[[CalendarViewController alloc] initWithNibName:#"CalendarViewController" bundle:nil] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[calendarVC];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
self.tabBarController.customizableViewControllers = nil;
return YES;
}
CalendarViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Row %#",[events objectAtIndex:indexPath.row] );
CalendarDetailVC *detailVC = [[CalendarDetailVC alloc] initWithNibName:#"CalendarDetailVC" bundle:nil];
detailVC.dictEvent = [events objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
}
You don't have a navigation controller in your hierarchy, so you can't so a push. You need to add a line to create the navigation controller,
calendarVC = [[[CalendarViewController alloc] initWithNibName:#"CalendarViewController" bundle:nil] autorelease];
UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController: calendarVC] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[nav];
Hi i am trying to make UINavigationController but not in mainViewController(first viewControllerClass) , i need to put UINavigationController in second class. But If i will write these codes in appDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
// [window addSubview:[navigationController view]];
UINavigationController *navigation = [[UINavigationController alloc]initWithRootViewController:self.viewController];
self.window.rootViewController = navigation;
[self.window makeKeyAndVisible];
return YES;
}
Then UINavigationController appears in mainView. I am trying to put it in other class like that
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// strWhichTaleOnScreen=[masivTaleNames objectAtIndex:indexPath.row];
NSString *selectDay;
selectDay=#"first string";
NSLog(#"selecDay=%#",selectDay);
classDetailOfMessagesViewController *nesneDetailOfMessagesViewController = [[classDetailOfMessagesViewController alloc] initWithNibName:#"classDetailOfMessagesViewController" bundle:nil];
nesneDetailOfMessagesViewController.selectDay = selectDay;
[navigation pushViewController: nesneDetailOfMessagesViewController animated:YES];
nesneDetailOfMessagesViewController = nil;
}
But it doesn't work, I guess i have to create rootViewController in this second view but i dont know how.
I ll be happy if someone can show me way to solve it out.
The first mistake i saw was you are trying to set the window rootviewcontroller twice. The view hierarchy needs to be like window->navigation controller->view controller. so I made some changes with your code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navigation = [[UINavigationController alloc]initWithRootViewController:self.viewController];
self.window.rootViewController = navigation;
[self.window makeKeyAndVisible];
return YES;
}
In the second code sample I couldn't find the reference to the navigation. And also if you push (in your case initWithRootViewController) a view controller to navigationcontroller stack you can access the navigation controller by self.navigationController so your second part of the code should be like this;
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *selectDay;
selectDay=#"first string";
NSLog(#"selecDay=%#",selectDay);
classDetailOfMessagesViewController *nesneDetailOfMessagesViewController = [[classDetailOfMessagesViewController alloc] initWithNibName:#"classDetailOfMessagesViewController" bundle:nil];
nesneDetailOfMessagesViewController.selectDay = selectDay;
[self.navigationController pushViewController: nesneDetailOfMessagesViewController animated:YES];
}
I have a tabBar application. One of the tabs has a rootviewcontroller that creates a UITableView and adds it to the subview. When a user clicks a cell in the UITableView I want to push a new rootviewcontroller but I cant get it to work.
In my appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Create the window
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
//Create the UIViewCOntrollers for each tab
_viewController1 = [[[LocavoreRetroFirstViewController alloc] initWithNibName:#"LocavoreRetroFirstViewController" bundle:nil] autorelease];
_viewController2 = [[[LocavoreRetroSecondViewController alloc] initWithNibName:#"LocavoreRetroSecondViewController" bundle:nil] autorelease];
UIViewController *viewController3 = [[[LocavoreRetroThirdViewController alloc] initWithNibName:#"LocavoreRetroThirdViewController" bundle:nil] autorelease];
_viewController4 = [[[LocavoreRetroFourthViewController alloc] initWithNibName:#"LocavoreRetroFourthViewController" bundle:nil] autorelease];
UIViewController *viewController5 = [[[LocavoreRetroFifthViewController alloc] initWithNibName:#"LocavoreRetroFifthViewController" bundle:nil] autorelease];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:_viewController1];
//[_viewController1 release];
NSArray* controllers = [NSArray arrayWithObjects:navigationController, _viewController2, viewController3, _viewController4, viewController5, nil];
//Create the tab controller
_tabBarController = [[[UITabBarController alloc] init] autorelease];
[_tabBarController setViewControllers:controllers];
//Initialize the tab controller with the views
// _tabBarController.viewControllers = #[_viewController1, _viewController2,
// viewController3, _viewController4, viewController5];
//Set the window to the tabcontroller view and make it visible
_window.rootViewController = _tabBarController;
_tabBarController.delegate=self;
[_window makeKeyAndVisible];
return YES;
}
In my subview didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RecipePageController *recipePageController = [[RecipePageController alloc] initWithNibName:#"RecipePageController" bundle:nil];
[self.navigationController pushViewController:recipePageController animated:YES];
[recipePageController release];
}
For each tab you need to create a separate navigation controller
I want set a tabbar in my app and in my appDelegate I do this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil] autorelease];
UIViewController *viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil] autorelease];
[viewController2 viewDidLoad];
UIViewController *viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil] autorelease];
[viewController3 viewDidLoad];
UIViewController *viewController4 = [[[FourthViewController alloc] initWithNibName:#"FourthViewController" bundle:nil] autorelease];
[viewController4 viewDidLoad];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[viewController1, viewController2, viewController3, viewController4];
self.viewController = [[[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
you can see that I want to start my app not immediately with tab bar, in fact I start my app with an HomeViewController
inside my HomeViewController i open viewController1 with:
FirstViewController *first = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
[self presentViewController:first animated:YES completion:nil];
[first release];
but in my firstviewcontroller I don't see my tabbar, why? (I state that the app work fine with tabbar if I start without homeviewcontroller)
You don't see tabbar because in HomeViewController you create new instance of FirstViewController and present it modally. You should create and present the whole UITabBarController inside HomeViewController:
AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.viewController = [[[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
inside HomeViewController:
FirstViewController *viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil] autorelease];
SecondViewController *viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil] autorelease];
ThirdViewController *viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil] autorelease];
FourthViewController *viewController4 = [[[FourthViewController alloc] initWithNibName:#"FourthViewController" bundle:nil] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[viewController1, viewController2, viewController3, viewController4];
[self presentViewController:self.tabBarController animated:YES completion:nil];
Ok, so I a a Master Detail application, and when a user clicks on a cell, it loads loads a webpage in the DetailViewController. The problem is, that on the iPhone version (this is a universal app) I have to click on the cell, then go back to the MasterViewController and then click on the cell again to load webpage. I only have to do this once, I think it is like initiating the webpage or something the first time. On the iPad version though, it loads it one the first time. So what's up?
Here is the code for my applicationDidFinishLaunching AppDelegate.m file, where I init the DetailViewController
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;
masterViewController.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController_iPhone" bundle:nil];
} else {
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController_iPad" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
masterViewController.detailViewController = detailViewController;
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = #[masterNavigationController, detailNavigationController];
self.window.rootViewController = self.splitViewController;
}
here is the code for the didSelectCellAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *object = _objects[indexPath.row];
NSURL *ex = [NSURL URLWithString:[object objectForKey:#"url"]];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.detailViewController.detailItem = object;
[self.detailViewController loadURL:ex];
self.detailViewController.detailItem = object;
[self.detailViewController loadURL:ex];
[self.navigationController pushViewController:self.detailViewController animated:YES];
} else {
self.detailViewController.detailItem = object;
[self.detailViewController loadURL:ex];
}
}
On the iPad, you have the 2 controllers in a split view controller, so they are instantiated, and their view's loaded when the app starts up. On the iPhone, that second controller is instantiated, but it's view isn't loaded until you push it -- I think that's the difference. You should try moving the detailController method loadURL: to it's viewDidAppear method, instead of having it in the master controller's didSelectRowAtIndexPath method.