Passing data between ViewController and TabBar children - iphone

I am developing an application which has a a TableView. When I press any cell the app goes to the next ViewController. In this viewController I have created a TabBarController by code which has 3 children ViewControllers. So, I want to pass a variable from the TableView to the Children of the TabBar. I can pass the variable to the TabBar, I have watched it with the NSlog function. It is really weird for me that in the children ViewControllers I also have type a NSlog and the variable is null, but in the output I see first this.
2013-10-01 03:01:40.687 Prototype[38131:c07] proId (null) // This is the children log from vc2 ViewController "YPProjectViewController"
2013-10-01 03:01:40.697 Prototype[38131:c07] projectID 433 // This is the TabBar LOG YPTabBarViewController
Does somebody know why I can first the Children NSLog? Maybe there is the solution.
#import "YPTabBarViewController.h"
#import "YPProjectViewController.h"
#import "YPCommentsViewController.h"
#import "YPProposalsViewController.h"
#interface YPTabBarViewController ()
#property (nonatomic,strong)UITabBarController *tabBar;
#end
#implementation YPTabBarViewController
#synthesize tabBar;
#synthesize projectId = _projectId;
- (void)viewDidLoad
{
[super viewDidLoad];
[self setUpTabBar];
}
// Set up tabBar
-(void)setUpTabBar
{
YPCommentsViewController *vc1 = [[YPCommentsViewController alloc] init];
vc1.title = #"Comments";
vc1.view.backgroundColor = [UIColor clearColor];
UINavigationController *contentNavigationController = [[UINavigationController alloc] initWithRootViewController:vc1];
YPProjectViewController *vc2 = [[YPProjectViewController alloc] init];
vc2.title = #"Project";
vc2.view.backgroundColor = [UIColor clearColor];
vc2.proId = _projectId;
NSLog(#"PROJECT ID %#", vc2.proId);
// UINavigationController *contentNavigationController2 = [[UINavigationController alloc] initWithRootViewController:vc2];
YPProposalsViewController *vc3 = [[YPProposalsViewController alloc] init];
vc3.title = #"Proposal";
vc3.view.backgroundColor = [UIColor clearColor];
UINavigationController *contentNavigationController3 = [[UINavigationController alloc] initWithRootViewController:vc3];
tabBar = [[UITabBarController alloc] init];
tabBar.viewControllers = #[contentNavigationController,vc2,contentNavigationController3];
tabBar.selectedIndex = 1;
[tabBar.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
[tabBar willMoveToParentViewController:self];
[self addChildViewController:tabBar];
[tabBar didMoveToParentViewController:self];
[self.view addSubview:tabBar.view];
}

In terms of understanding the problem, your NSLog statement in the "tab bar controller" is logging the value of vc2.proID immediately after setting it. But your NSLog output show us that that second tab's view controller is logging its results before that. That's why it's nil when the second tab's view controller's viewDidLoad logs it, because that log is happening before the tab bar controller had a chance to set the value and log it itself.
So, there are a couple of ways you could fix this:
Right before your assignment of vc2.proId, you have an innocuous line of code that says:
vc2.view.backgroundColor = [UIColor clearColor];
That line of code triggers the second view controller's view to be loaded (and its viewDidLoad will be called). If you move the assignment of vc2.proId to before you start accessing any of vc2's views, that will change the order that your NSLog statements appear (or, much better, move the setting of the background color into viewDidLoad of the child controllers).
You could just create your own init method that accepts the project id as a parameter. That would also ensure that it's set before viewDidLoad. Thus, YPProjectViewController could have a method such as:
- (id)initWithProjectId:(NSString *)projectId
{
self = [self init];
if (self)
{
_proId = projectId;
}
return self;
}
Two unrelated observations regarding the custom container calls:
When you call addChildViewController, it calls willMoveToParentViewController for you. So you should remove the call to willMoveToParentViewController. See the documentation for that method.
You might even want to retire these custom container calls altogether, and just make YPTabBarViewController a subclass of UITabBarController, itself, rather than UIViewController. That eliminates the need to custom container calls altogether. Clearly, if you have other needs for the custom container, then feel free, but it's redundant in this code sample.

Related

page-based app with uitableview; how to show detail view and show another data in the table when goes to next page?

I have page-based app. On each page I have 3 uibuttons at the top, uiscrollview with alphabet (uibuttons to sort data in uitable) at the right and uitableview at the center. How to show cell's detail view? If it is necessary to add uinavigationcontroller I can't do this. If I adds it, it disables interaction with my table, buttons and scrollview.
And another question is how to show new data in tableview and scrollview when goes to next page??
I have rootViewController class and DataViewController class.
rootViewController listing:
#interface RootViewController ()
#property (readonly, strong, nonatomic) ModelController *modelController;
#end
#implementation RootViewController
#synthesize pageViewController = _pageViewController;
#synthesize modelController = _modelController;
#synthesize navContr = _navContr;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
//[self presentModalViewController:navContr animated:YES];
self.pageViewController = [[[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil] autorelease];
self.pageViewController.delegate = self;
DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = [NSArray arrayWithObject:startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
self.pageViewController.dataSource = self.modelController;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
self.navContr = [[UINavigationController alloc] initWithRootViewController:self.pageViewController];
[self.view addSubview:self.navContr.view];
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
CGRect pageViewRect = self.view.bounds;
self.pageViewController.view.frame = pageViewRect;
[self.pageViewController didMoveToParentViewController:self];
// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
for (UIGestureRecognizer *recognizer in self.pageViewController.gestureRecognizers){
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]){
[recognizer setEnabled:NO];
}
}
}
After few manipulations it works but I need help to get it work fine!
So now it looks like this
Next question: how do I remove the brown space at the top???
::UPDATE::
Problem solved. It needs just to set y-axis position of UINavigationController to -20 ;)
i'm not sure if this link about creating navigation-based project may help you.. (http://iosmadesimple.blogspot.com/2012/08/navigation-based-project-doing-it.html)
From that tutorial, there's a class called SampleViewController, subclass of UIViewController. You might want to put a tableView in SampleViewController.xib file. Then in your SampleViewController.h file, add an IBOutlet UITableView* yourTable property and synthesize it. Connect it to your tableView in your .xib file. //Or you may do it programmatically
in your SampleViewController.h, make your interface header look like this.. I think you already know this...
#interface SampleViewController:UIViewController < UITableviewDelegate, UITableViewDatasource >
in your SampleViewcontroller.m, under viewDidLoad method, set the table delegate and datasource to self:
yourTableView.delegate = self;
yourTableView.datasource = self;
Afterwhich, you implement tableView delegate and datasource methods... //you already know those since you were already able to show a tableview ;)
one of these methods is the "tableview:didSelectAtIndexpath:" --> this is the part wherein you can put your code when you click one of the cells.
Let's assume you have the DetailsViewController Class, this is the class you would like to show after clicking a cell and show its details.
DetailsViewController Class must have a variable that will accept the data you would like to show. Let's say, an NSString *detailsMessage; //do the #property and #synthesize thing...
Let's go back to SampleViewController.m file, under tableview:didSelectAtIndexpath: Method:
inside that Method.. put these codes.
DetailsViewController *detailsVC = [[DetailsViewController alloc] init];
detailsVC.detailsMessage = #"The Data you want to pass.";
[self.navigationController pushViewController:detailsVC animated:YES];
I hope this helps. :(
There may be other ways but by far the easiest way is to use a navigation controller. In fact, it is built to do exactly this.
If you don't want the navigationBar then you can hide it in the viewWillAppear function.
[self.navigationController setNavigationBarHidden:YES animated:YES];
Then you can add an other UIViewController to push when the user selects a cell.
Having read your OP again I'm not sure how you are adding your navigationController.
To use a navigationController you create it and load it at start time. You then create your current viewController (the one with the buttons and table etc...) and set this as the rootViewController of the navigationController.
Then you display the navigationController.
Could you explain how you are adding your navigationController as it may help understand what is going wrong.
Thanks
::EDIT::
OK, my assumption was correct.
The way you are using the navigation controller is not how it was intended.
OK, so at the moment your AppDelegate file will have a method Application didFinishLaunching...
It will look something like this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
You should change it so that it is like this...
first add a property to your appDelegate...
#property (nonatomic, strong) UINavigationController *navigationController;
Then change the didFinishLaunchingMethod to this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
This will still show you MainViewController but it will now be contained within a navigationController.
Next in your MainViewController function viewWillAppearAnimated add the line...
[self.navigationController setNavigationBarHidden:YES animated:animated];
This will then hide the navigationBar at the top of the view so you still have access to your buttons.
The you need a new ViewController and xib file (for example DetailViewController).
When the user selects a table row you need to then do something like...
DetailViewController *detailView = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
//pass in details of which row was selected.
[self.navigationController pushViewController:detailView animated:YES];
This will then display your new view and new viewController. You will also need to write a way of passing the data in (set up a property on the DetailViewController).
Hope this helps.

Programmatically setting UITabBarItem icons with StoryBoards?

I want to use a UITabBarSystemItem for the icon of one of my tabBarItem's but I'm using storyboards. I'm not sure where to set it. If I set it in the view's viewDidLoad then it doesn't change until you push the button in the tabBar. Before that it's just the blue ? square.
And as far as I know, you can't use UITabBarSystemItems in IB inspector.
UPDATE:
Well first of all I'm an idiot. You can totally choose the icon in the IB Inspector.
Tab Bar Item -> Identifier -> Choose your icon.
But the question still remains how to do it programmatically. Or rather when/where?
When using storyboards, a view controller initializes using the initWithCoder constructor so you could override that function and set the system item icon there like so
- (id)initWithCoder:(NSCoder*)aDecoder
{
if(self = [super initWithCoder:aDecoder])
{
self.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFavorites tag:1];
}
return self;
}
Naturally, you can change the value of the system item to any of the values supported. Apple lists them here
Check this code for your problem: Its working in my app.
- (NSArray *) initializeViewControllers
{
NSArray *viewControllerArray = nil;
viewController1 = <View Init Code>
viewController2 = <View Init Code>
viewController3 = <View Init Code>
1stNavController = [[UINavigationController alloc] initWithRootViewController:viewController1];
UIImage *img = [UIImage imageNamed:#"tab_home"];
[1stNavController .tabBarItem initWithTitle:#"Home" image:img tag:1];
2ndNavController = [[UINavigationController alloc] initWithRootViewController:viewController2];
img = [UIImage imageNamed:#"tab_timeDrop"];
[2ndNavController .tabBarItem initWithTitle:#"Time Entry" image:img tag:2];
3rdNavController = [[UINavigationController alloc] initWithRootViewController:viewController3];
img = [UIImage imageNamed:#"tab_invoiceSummary"];
[3rdNavController.tabBarItem initWithTitle:#"Invoice Summary" image:img tag:3];
viewControllerArray = [NSArray arrayWithObjects:1stNavController,2ndEntryNavController,3rdReportNavController, nil];
return viewControllerArray;
}
This code is returning View Controllers with Images for their respective tabs. Here i used Navigation Controller inside the tabbar controller. you can also use view controller instead of navigation Controller.
Just add this code and initialize your tabbar controller as follows inside appdidfinishlaunching method:
tabbarController = [[UITabBarController alloc] init];
_tabbarController.viewControllers = [self initializeViewControllers];
self.window.rootViewController = tabbarController;
Hope it works.
Please reply.
Well that's quite simple!
For the where -> create a custom TabBarController (e.g. WBTabBarController).
In your StoryBoard explicitly set it.
For the how -> just overwrite viewDidLoad of the WBTabBarController and set your images for the TabBarItems. In the following example this was done using the NIKFontAwesomeIconFactory:
#import "WBTabBarController.h"
#import "NIKFontAwesomeIcon.h"
#import "NIKFontAwesomeIconFactory.h"
#import "NIKFontAwesomeIconFactory+iOS.h"
#interface WBTabBarController ()
#end
#implementation WBTabBarController
- (void)viewDidLoad
{
[super viewDidLoad];
NIKFontAwesomeIconFactory *factory = [NIKFontAwesomeIconFactory tabBarItemIconFactory];
UITabBarItem *item0 = self.tabBar.items[0];
item0.image = [factory createImageForIcon:NIKFontAwesomeIconApple];
UITabBarItem *item1 = self.tabBar.items[1];
item1.image = [factory createImageForIcon:NIKFontAwesomeIconStackOverflow];
}
#end
Assuming the initial scene of your storyboard is the tab bar view controller, you can access it in applicationDidFinishLaunching, it is the rootViewController of the app delegate's window. I don't know if you can swap in a system item if the bar item is already present, but you can definitely set the image and title.

Back button does not appear in navigation bar until you rotate

I have three view controllers: A -> B -> C managed by a navigation controller. A is a transient view controller. It asks the server for something. If the server says everyhing is OK, then A pushes B onto the stack. B must hide the back button because I don't want users to manually go back to A.
// B view controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.hidesBackButton = YES;
self.title = #"B";
}
B then pushes C onto the stack when the user taps a table cell.
// B view controller
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
C *c = [[C alloc]
initWithStyle:UITableViewStyleGrouped
];
[self.navigationController
pushViewController:c
animated:YES
];
[c release];
}
.
// C view controller
- (void) viewDidLoad
{
[super viewDidLoad];
self.navigationItem.hidesBackButton = NO;
self.title = #"C";
}
If all goes well, the flow should look like this:
------------- ------------- -------------
|_____A_____| |_____B ____| | <B|__ C___|
| | => | | => | |
| loading...| | cells | | detail |
| | | | | |
------------- ------------- -----------
For some reason, C does not show a back button to go back to B until I rotate the device. Once rotated, the back button appears in all orientations. The problem seems to stem from B hiding the back button and C trying to reveal it again, because If I don't let B hide it, I don't have this problem. So how do I get C to show the back button without forcing the user to rotate the device like a monkey?
Update
Broken on two different Verizon iPhone 4 both on iOS 4.2.10
Fine on AT&T iPhone 3GS on iOS 5.0
Fine on AT&T iPhone 4 on iOS 4.3
After some searching I found this solution for iPhone 4.2 (since you posted that it works on later versions) on some old forum post.
-(void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.hidesBackButton = YES;
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.navigationItem.hidesBackButton = NO;
}
Mayhaps this will help you out.
(Check this out: Back button don't appear in navigationController)
I think you need to put your code like this for C
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.navigationItem.hidesBackButton = NO;
}
I had this problem once and solved it by giving B's navigation item a title
// B view controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.hidesBackButton = YES;
self.navigationItem.title = #"What you want C's back button to say";
self.title = #"B";
}
If you don't want the title to appear in B you can set B's navigationItem's titleView to an empty view. About the titleView property:
If this property value is nil, the navigation item’s title is displayed in the center of the navigation bar when the receiver is the top item. If you set this property to a custom title, it is displayed instead of the title. This property is ignored if leftBarButtonItem is not nil.
Try adding this to your class C:
-(id) init
{
[super init];
self.navigationItem.hidesBackButton = NO;
}
Not sure if this will work for your back button situation but I know that when I use a custom back button I need to set the custom back button on the alloc'd item before I push it (not self like the post above). Hopefully it will work for your situation as well - worth a try.
In other words, try:
// B view controller
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
C *c = [[C alloc]
initWithStyle:UITableViewStyleGrouped];
// *** set on c's navigationItem (not self) before you push
[[c navigationItem] setHidesBackButton: NO];
[self.navigationController
pushViewController:c
animated:YES
];
[c release];
}
Try to put self.navigationItem.hidesBackButton = NO; into the init method or anywhere before the pushViewController call.
ViewDidLoad is called when you ask the controller for the view for the first time, that means, it is probably called from [self.navigationController pushViewController:c animated:YES]. But note that the navigation bar is not part of your view, it is created and handled by UINavigationController, so basically it can exist and be drawn even before viewDidLoad and viewDidAppear is called. If you update navigation bar there, it doesn't get actually repainted.
Edit 1: Revisited after reading the documentation for [UIViewController navigationItem]
You should avoid tying the creation of bar button items in your navigation item to the creation of your view controller’s view. The navigation item of a view controller may be retrieved independently of the view controller’s view. For example, when pushing two view controllers onto a navigation stack, the topmost view controller becomes visible, but the other view controller’s navigation item may be retrieved in order to present its back button. To ensure the navigation item is configured, you can override this property and add code to load the bar button items there or load the items in your view controller’s initialization code.
Edit 2: Revisited after reading the comment that my solution does not work. Working code (iOS 5, ARC):
//
// TestAppDelegate.m
// NavigationTest
//
// Created by Sulthan on 10/25/11.
// Copyright (c) 2011 StackOverflow. All rights reserved.
//
#import "TestAppDelegate.h"
#interface TestAppDelegate ()
#property (nonatomic, strong, readwrite) UINavigationController* navigationScreen;
#property (nonatomic, strong, readwrite) UIViewController* screen1;
#property (nonatomic, strong, readwrite) UIViewController* screen2;
#property (nonatomic, strong, readwrite) UIViewController* screen3;
#end
#implementation TestAppDelegate
#synthesize window = window_;
#synthesize navigationScreen = navigationScreen_;
#synthesize screen1 = screen1_;
#synthesize screen2 = screen2_;
#synthesize screen3 = screen3_;
- (UIViewController*)createTestScreenWithLabel:(NSString*)label {
CGRect bounds = [[UIScreen mainScreen] bounds];
UIViewController* screen = [[UIViewController alloc] init];
screen.view = [[UILabel alloc] initWithFrame:bounds];
screen.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
((UILabel*) screen.view).textAlignment = UITextAlignmentCenter;
((UILabel*) screen.view).text = label;
return screen;
}
- (void)pushThirdScreen {
if (!self.screen3) {
self.screen3 = [self createTestScreenWithLabel:#"Screen 3"];
self.screen3.navigationItem.hidesBackButton = NO;
}
[self.navigationScreen pushViewController:self.screen3 animated:YES];
}
- (void)pushSecondScreen {
self.screen2 = [self createTestScreenWithLabel:#"Screen 2"];
self.screen2.navigationItem.hidesBackButton = YES;
UIBarButtonItem* button = [[UIBarButtonItem alloc] initWithTitle:#"Go"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(pushThirdScreen)];
self.screen2.navigationItem.rightBarButtonItem = button;
[self.navigationScreen pushViewController:self.screen2 animated:YES];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
CGRect bounds = [[UIScreen mainScreen] bounds];
self.screen1 = [self createTestScreenWithLabel:#"Screen 1"];
self.navigationScreen = [[UINavigationController alloc] initWithRootViewController:self.screen1];
self.window = [[UIWindow alloc] initWithFrame:bounds];
self.window.backgroundColor = [UIColor whiteColor];
[self.window addSubview:self.navigationScreen.view];
[self.window makeKeyAndVisible];
[self performSelector:#selector(pushSecondScreen) withObject:nil afterDelay:3.0];
return YES;
}
#end
Edit 3: Revisited after noticing that you are speaking mainly about iOS 4.2. I can't currently test it on any iOS 4.2 but I know about a possible workaround. You can always hide the navigation bar in your UINavigationController and just put a separate navigation bar into each screen. You will have absolute control over them and you can even edit them in Interface Builder.

UITabBarController only showing half of its UITabBar (off screen)

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.

How do I pushViewController/etc. from a UIViewController subclass?

I've been attempting to figure this out for a while now, but I'm up to a point where I can't seem to solve my problem from reading other Q&As. I'm trying to get the active UIViewController in a UINavigationController to send popViewController/pushViewController messages to the UINavigationController, but I cannot figure it out. I'm probably doing something rather stupid that is causing it to break. The structure should be like this, but even then I'm not sure if I've done that right.
mainController
primaryNavigationController
firstViewController
secondViewController
both firstViewController and secondViewController are a subclass
mainController.m
firstViewController = [[FirstTestViewController alloc] init];
secondViewController = [[FirstTestViewController alloc] init];
primaryNavigationController = [[UINavigationController alloc]
initWithRootViewController:firstViewController];
[primaryNavigationController.view setFrame:CGRectMake(0,0,320i,409)];
[self.view addSubview:[primaryNavigationController view]];
[primaryNavigationController.navigationBar setFrame:CGRectMake(0,0,20,44)];
primaryNavigationController.navigationBar.tintColor = [UIColor blackColor];
How can I tell primaryNavigationController to push/pop a VC from within the firstTestViewController subclass?
You would allocate the second view controller within your first view controller (because you don't need it before):
secondViewController = [[FirstTestViewController alloc] init];
[self.navigationController pushViewController:secondViewController animated:YES];
[secondViewController release];
The SDK includes many sample projects that involve a navigation controller and show you how to do this.