Objective-c Nested VIewControllers - objective-c

i would like to create an App whit a structure similar to the native application "Phone" of the iPhone. I will be more precise, the phone application have a tabBar that contains:"Favorites" , "Recents", "Contact", "Keypad" and "Voice Mail".
When we enter in the tab contacts we can see a navigation bar and a tableView.
I would like to have a similar structure but i'm questioning myself about which is the best and most correct way to do it?
I was thinking to start a single view application than use the view controller that is create automatically as a TabbedViewController then i would create another subclass of another viewController and i used it as my NavViewController.
I would have something like
[myTabBar.view addSubview:myNavController];
but how can i set those instance? once i have the automatically created ViewController and i create a SecondviewController how can i set them as the TabViewController and my NavViewController ?

If you're using storyboards, just add a tab bar controller to your storyboard. Then select one of the tab bar's child scenes and then choose "Embed In" - "Navigation Controller" from the Xcode "Editor" menu. If you repeat that process for whichever tabs you want to have navigation controllers. In this screen snapshot, I've added a navigation controller to the first and third tabs, but not the second.
Hopefully this illustrates the idea.
If you're determined to do this with NIBs, the easiest way to get started is create a new project with the Tabbed Application template (and obviously, at the next screen, uncheck "Use Storyboards"):
Then open up the app delegate .m file and replace the default didFinishLaunchingWithOptions that looks like:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[viewController1, viewController2];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
with one that creates a separate navigation controller for each tab for which you want a navigation bar (in this case, I'm adding it to the first one only, but it illustrates the idea):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UINavigationController *navigationController1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[navigationController1, viewController2]; // was #[viewController1, viewController2];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
This a relatively easy way to start a NIB-based tabbed application. You can then customize from there.
Personally, I struggle to imagine why someone would use NIBs rather than storyboards (unless you're trying to support iOS 4), but hopefully this illustrates both techniques.

Related

iOS 7 - Setting the current view controller as root of navigation

I need to set the view controller of the home screen as the the root of the navigation controller, no matter how the user reaches it (push/show or custom segue)
The following code put in the viewDidLoad of a view controller seems to have no effect with iOS 7:
[self.navigationController setViewControllers:#[self]];
The navigation stack does not change at all.
Have you ever experienced any similar issue?
Thanks,
DAN
Call your UIViewController method from app delegate like this..try it out.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController* pp = [[ViewController alloc] init];
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:pp];
self.window.rootViewController = nav; or [self.window setrootviewcontroller=nav];
[self.window addSubview:[nav view]];
[self.window makeKeyAndVisible];
Only one line to make your current viewController as rootviewcontroller
[[[UIApplication sharedApplication] delegate] window].rootViewController = self;
Create global reference of navigation controller in App Delegate and then with the reference of appDelegate you can change you rootView controller anywhere just type below code :
[appDelegate.navigaitonController initWithRootViewController:viewController];
Note: Here viewController is new viewcontroller reference which you want to set as root of navigation controller .

Why is the view from my XIB file not being loaded by the UIViewController?

In my app delegate, I have:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[CGMContainerViewController alloc] init];
self.window.rootViewController = self.viewController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
I have an unmodified CGMContainerViewController.h/m and a modified CGMContainerViewController.xib (added a button). The view is linked to the File Owner.
Why is the view from the XIB not showing?
EDIT: Is it because I'm trying to load a view with a status bar into the window?
From the looks of your code, you aren't loading any XIB files. You need to call initWithNibName:
self.viewController = [[CGMContainerViewController alloc] initWithNibName:
#"CGMContainerViewController" bundle: nil];
Make sure that your File's Owner in the XIB is set to CGMContainerViewController
Okay. I think it was because for a UINavigationController, you have to set the rootViewController and all the layers. I just changed it to a UIViewController because I didn't really need the navigation, just the navigation bar.
The problem which I faced is .If you name your viewController with special character with "-" and some other things your xib will not get loaded
example--> (wrong naming)
view-controller1 (If naming is like this then the xib wont get loaded)
example--->(correct naming)
viewController1 (xib will get loaded)

UITabbar disappear when pushing

i'm having trouble with a navigation Controller, when i'm pushing my view controller to an xib a see a UITabbar but in mij xib where i'm pushing the view to i'm doing this to push the xib where i'm pushing to, to another file but when i use this line of code the UITabbar doesn't show up.
What i'm doing in view controller 1 i check if a JSON file contains 0,1 or 2 items when it's for example '1' item in the JSON i would like to push the view controller to a file special for the '2 item file' i'm pushing on this way:
UIViewController *rootController =
[[2ViewController alloc]
initWithNibName:#"2ViewController" bundle:nil];
navigationController = [[UINavigationController alloc]
initWithRootViewController:rootController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
But when i do that the UITabbar disappear 'under' the view controller. Could somebody help me out solving this problem please?
you set set navigationController into UITabBarController.
Like
//Add to tabbars.
NSArray* controllers = [NSArray arrayWithObjects:navigationController, nil];
myTabBarController.viewControllers = controllers;

UINavigationController — left and right flip animation between pushes and pops when presented via presentViewController

Supposed you've got:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *rootViewController = [[UIViewController alloc] init];
rootViewController.view.backgroundColor = [UIColor whiteColor];
[self.window setRootViewController:rootViewController];
[self.window makeKeyAndVisible];
UINavigationController *modal = [[UINavigationController alloc] initWithRootViewController:[[PTFrontViewController alloc] init]];
modal.modalPresentationStyle = UIModalPresentationFormSheet;
[rootViewController presentViewController:modal animated:YES completion:NULL];
return YES;
}
whereas PTFrontViewController and PTBackViewController view controllers have nothing interesting for sake of this example.
How could you push an instance of PTBackViewController from PTFrontViewController animating as in UIViewAnimationTransitionFlipFromLeft or UIViewAnimationTransitionFlipFromRight?
I am already well aware of these three things:
this is not exactly how you should make use of presentViewController
there is a good reason for UINavigationController's default animation
there are several answers how to "customize" UINavigationController's default animation while pushing and poping, but if you try the code for your self you will notice that when a view controller is presented via presentViewController there are drop shadows and background views that won't get animated correctly
So please answer taking these things in mind. Thank you.
First - forget UINavigationController. If you don't need the default animation, just put a UINavigationBar into your controllers. It will get a little easier.
Second - this is a difficult problem, you can't create such an animation only within the modal controller because the background wouldn't be repainted.
Sincerely, the easist solution I see is too forget the modal controller and just add the view controller as a child of your root controller. Then you can control all the animations but you have to write everything by yourself (including the background fading).

UINavigationController for table inside of UITabController

my app is built with a UITabController and works as imagined. However, for one of the views within my UITabBar, I would like to add a table that when something is pressed will take me somewhere. And I would like to do this just within this one view.
I know how to build a table and populate and get it to go somewhere but my issue is I can't seem to get my app to run with the table. I feel like my connections are off and specifically with appDelegates. I already had two appDelegate files (.h & .m) before adding the UINavigationController so from here I really don't know what to do. I took apple's simpleTableView tutorial files and copied them over to mine. It still crashes. I even copied there appDelegate files (so now I have 4) but the same deal. This is the error I am getting but in general I just feel lost with the delegates and connections.
2011-12-12 12:08:50.302 TabbedCalculation[68713:207] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key delegate.'
* Call stack at first throw:
If anyone can offer any help, it would be much appreciated.
Thanks!
P.S. I have changed within the mainWindow.xib of the UITabController to point one of the tabs to the appropriate class and xib file so that is not the issue but I have noticed that many tutorials want within the app delegate this line to the navController:
[window addSubview:[navigationController view]];
but I have already set it to the tabBarController.
Your app can only use one set of app delegate files. So copying over a the example's app delegate files does not mean they are being utilized. You need a navigation controller inside the specific tab you want to contain the tableview. Here is an example of a navigation controller inside a tab bar controller, by modifying didFinishLaunchingWithOptions in the app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
AllTaskViewController *view1 = [[AllTaskViewController alloc] initWithNibName:#"AllTaskView" bundle:nil];
view1.title = #"All Tasks";
TodayTaskViewController *view2 = [[TodayTaskViewController alloc] initWithNibName:#"TodayTaskView" bundle:nil];
view2.title = #"Today's Tasks";
HistoryViewController *view3 = [[HistoryViewController alloc] initWithNibName:#"HistoryView" bundle:nil];
view3.title = #"History";
SettingsTableViewController *view4 = [[SettingsTableViewController alloc] initWithNibName:#"SettingsTableView" bundle:nil];
view4.title = #"Settings";
UINavigationController *nav1 = [[UINavigationController alloc] initWithRootViewController:view1];
UINavigationController *nav2 = [[UINavigationController alloc] initWithRootViewController:view2];
UINavigationController *nav3 = [[UINavigationController alloc] initWithRootViewController:view3];
UINavigationController *nav4 = [[UINavigationController alloc] initWithRootViewController:view4];
[view1 release];
[view2 release];
[view3 release];
[view4 release];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:nav1, nav2, nav3, nav4, nil];
[nav1 release];
[nav2 release];
[nav3 release];
[nav4 release];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Note: All 4 view controllers have an individual navigation controller, and each one is a custom view controller. I used nibs here, but you don't necessarily have to. And the app itself has no main window, you would need to modify this slightly if you are using a main window for the app.