Loading a view controller & view hierarchy programmatically in Cocoa Touch without xib - iphone

It seems like all of the Cocoa Touch templates are set up to load a nib.
If I want to start a new project that's going to use a view controller, and load its view(hierarchy) programatically, not from a nib/xib, what are the steps to setting that up or adjusting a template.
I though all I had to do was implement -loadView, but I have trouble every time I try to do this.

It's reasonably simple to do completely programmatic user interface generation. First, you need to edit main.m to look something like the following:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
UIApplicationMain(argc, argv, nil, #"MyAppDelegate");
[pool release];
return 0;
}
where MyAppDelegate is the name of your application delegate class. This means that an instance of MyAppDelegate will be created on launch, something that is normally handled by the main Nib file for the application.
Within MyAppDelegate, implement your applicationDidFinishLaunching: method similar to the following:
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if (!window)
{
[self release];
return;
}
window.backgroundColor = [UIColor whiteColor];
rootController = [[MyRootViewController alloc] init];
[window addSubview:rootController.view];
[window makeKeyAndVisible];
[window layoutSubviews];
}
where MyRootViewController is the view controller for the primary view in your window. This should initialize the main window, and add the view managed by MyRootViewController to it. rootController is kept as an instance variable within the delegate, for later reference.
This should let you programmatically generate your user interface through MyRootViewController.

UIViews themselves do not have a hierarchy, UINavigationControllers do. So init one of those, and pop a UIViewController onto it's stack. This should do it, in the most basic way possible, with no XIB files at all. You should be able to build on this.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UINavigationController *navController = [[UINavigationController alloc] init];
UIViewController *viewController = [[UIViewController alloc] init];
// set the properties of viewController here, to make it look like you want
[navController pushViewController:viewController animated:NO];
[window addSubview:navController.view];
// Don't forget memory management
[navController release];
[viewController release];
[window makeKeyAndVisible];
}

Related

How to code a back button on the a navigation bar using a bar button item

I'm having trouble coding a button to go to the previous page. I was able to do it to go to the next page thinking if I did the same thing but changed it a bit it would work in reverse. Unfortunately, I come up with a lot of errors I can't resolve because it won't allow me to use the release function.
This is this the code that helps it to work going to the next page fine:
#import "ViewController.h"
#implementation ViewController
-(IBAction)btnClicked:(id) sender
{
//add the view of the view controller to the current View---
if (menuView==nil) {
menuView =
[[MenuView alloc] initWithNibName:#"MenuView"
bundle:nil];
}
[self.view addSubview:menuView.view];
}
-(void)dealloc {
[menuView release];
[super dealloc];
}
How do I do it so that a back button will go to the previous page though.
It's pretty simple, use this :
-(IBAction)back:(id) sender
{
[menuView.view removeFromSuperview];
}
But, I would suggest not using addSubview: for many views as it would be complex way to do. Use UINavigationController as #Paul.s suggested.
The way you are doing this is not quite correct and I would suggest doing some reading to get familiar with iOS programming.
Your program structure should be: create a navigation controller (2) to manage the stack of view controllers giving it a viewController (1) to act as it's root.
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// 1
FirstViewController *firstViewController = [[FirstViewController alloc] init];
// 2
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
[firstViewController release]; firstViewController = nil;
self.window.rootViewController = navigationController;
[navigationController release]; navigationController = nil;
[self.window makeKeyAndVisible];
return YES;
}
This will display your first view controller inside a UINavigationController. A UINavigationController is responsible for managing a stack of UIViewController's and giving you UI to navigate back down the stack as well as calling all the appropriate presentation related methods on a UIViewController at the correct times e.g. viewDidLoad. You should check out The View Controller Programming Guide for lots of info
Then inside your first view controller you do something like this to respond to the button:
- (IBAction)buttonClicked:(id)sender;
{
SecondViewController *secondViewController = [[SecondViewController alloc] init];
[self.navigationController pushViewController:secondViewController animated:YES];
[secondViewController release]; secondViewController = nil;
}
This creates a new view controller and pushes it onto the stack.

Starting an App up with a different XIB

I want to start my app up with a different Xib. How would I do this?
Thanks
If you're using interface builder:
Under SupportingFiles, in -info.plist, look for a key named "Main nib file base name". Change that to the XIB you want it to load first
You can also take that entry out of the plist altogether an in main.m give it your appDelegate's name:
int retVal = UIApplicationMain(argc, argv, nil, #"HelloViewAppDelegate");
Then in your appDelegate, you can manually load your first view controller based on your code and logic. Personally, I like this better because it's much clearer to - here's my delegate and code to load it. It doesn't have all the bindings in IB I need to remember.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
CGRect screenBounds = [[UIScreen mainScreen] applicationFrame];
CGRect windowBounds = screenBounds;
windowBounds.origin.y = 0.0;
// init window
[self setWindow: [[UIWindow alloc] initWithFrame:screenBounds]];
// init view controller
_mainViewController = [[MainViewController alloc] init];
[[self window] addSubview:[_mainViewController view]];
[self.window makeKeyAndVisible];
return YES;
}
EDIT:
Answering your comment below. You pasted this invalid code:
// init view controller
ViewController = [[ViewController alloc] init];
[[self window] addSubview:[ViewController view]];
That's not valid. you need an instance variable name. By referring to it as "ViewController" your attempting to call class member variables. If your class is called ViewController then it should be:
// notice the instance myviewController is of type ViewController
ViewController *myViewController = [[ViewController alloc] init];
// notice calling view against instance (myViewController)
[[self window] addSubview:[myViewController view]];
At this point, if it's not compiling you need to edit your question and paste your main.m and appDelegate exactly as is into the question.
The MainWindow.xib file is just a shell that provides the application's UIWindow. While you can put a UIViewController in MainWindow.xib, you can also just have an unconnected UIViewController outlet on your app delegate and pick which nib to load at runtime in your application:didFinishLaunchingWithOptions: method, e.g.:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)options {
if (case1)
self.viewController = [[[MyViewController1 alloc] initWithNibName:nil bundle:nil] autorelease];
else if (case 2)
self.viewController = [[[MyViewController2 alloc] initWithNibName:nil bundle:nil] autorelease];
else
self.viewController = [[[MyViewController2 alloc] initWithNibName:nil bundle:nil] autorelease];
[window addSubview:self.viewController.view];
[window makeKeyAndVisible];
return YES;
}

How to show UINavigationController on view

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
MainPageDialog *overviewViewController = [[MainPageDialog alloc] initWithNibName:#"MainPage" bundle:nil];
UINavigationController *nav_obj = [[UINavigationController alloc] initWithRootViewController:overviewViewController ];
[self.viewController presentModalViewController:nav_obj animated:YES];
[overviewViewController release];
[self.window makeKeyAndVisible];
return YES;
}
This code shows the blue bar of navigation controller, but no buttons on it.It seems like to be that the UINavigationController allocated as empty.
Who knows what problems is?
UPD:Archive http://www.mediafire.com/?lbjjvl6fcue2q18
Please help me, I'm new in objective-c
You need to create the button for it, for example:
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:launcherView action:#selector(endEditing)];
self.navigationItem.leftBarButtonItem = doneButton;
[doneButton release];
The correct way to use a UINavigationController is to push view controllers on to it. That way they will be stacked and the navigation bar will be populated with a back button when it is case (i.e., when you can actually go back to a previous controller). You control the label that appears in the "back" button by defining the title of the controllers you push.
The technique shown in another answer (setting explicitly the button) is useful with defining the right button, if you ever need one.
You could try with this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MainPageDialog *overviewViewController = [[MainPageDialog alloc] initWithNibName:#"MainPage" bundle:nil];
UINavigationController* navigation = [[UINavigationController alloc] init];
[navigation pushViewController:overviewViewController animated:NO];
[overviewViewController release];
[window addSubview:[navigation view]];
[self.window makeKeyAndVisible];
return YES;
}
Instead of doing:
UINavigationController* navigation = [[UINavigationController alloc] init];
[navigation pushViewController:overviewViewController animated:NO];
you could also use initWithRootController, but to display the general case of how you push a view controller I preferred this one.
Notice that since you are pushing just a root controller, you should see no back button at the moment, but if you push a second view controller, then it will appear.
EDIT: I gave a look at your project. Summary of what you should try and do:
objects you need in your NIB: File's Owner (UIApplication), First Responder, FBFun App Delegate (iVkAppDelegate), Window (UIWindow); remove the rest;
File's owner delegate outlet is FBFun App Delegate;
FBFun App Delegate window outlet is Window.
With this simple setup (more or less what you have), use this code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UINavigationController* navigation = [[UINavigationController alloc] init];
//-- MainPageDialog *overviewViewController = [[MainPageDialog alloc] initWithNibName:#"MainPage" bundle:nil];
iVkViewController *overviewViewController = [[iVkViewController alloc] init];
overviewViewController.title = #"First";
[navigation pushViewController:overviewViewController animated:NO];
iVkViewController *overviewViewController2 = [[iVkViewController alloc] init];
overviewViewController2.title = #"Second";
[navigation pushViewController:overviewViewController2 animated:NO];
[overviewViewController release];
[window addSubview:[navigation view]];
[self.window makeKeyAndVisible];
return YES;
}
In the code above, as you notice, I instantiated twice your iVkViewController just to have a second controller to push onto the navigator.
Please, delete your existing app from the simulator, and the run this in order to see that the navigation bar is correctly created and you can go back from the second controller to the first one.
I removed usage of MainPageDialog, because the MainPage nib has many problems.
But I hope this skeleton is sufficient for you to go forward with your development.
You had missed the line as you are not adding view to window.Add this line in your code
[window addSubview:nav_obj.view];

Navigation Controller does not load views

I have custom view controller named DRTableViewController
In my app delegate, I use the following function to load
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
tvc = [[DRTableViewController alloc] init]; // tvc is created with xib
navCon = [[UINavigationController alloc] initWithRootViewController:tvc];
[self.window addSubview:[navCon view]];
[navCon release];
[self.window makeKeyAndVisible];
return YES;
}
but when I start my application, navigation controller appears but the view inside it is black,
when I use
[self.window addSubview:[tvc view]];
instead of [navCon view]; I can see my view without any problem
Thanks in advance
You need to retain your navigation controller so it is not released.
Create a property for you navigation controller and retain it in the application delegate.
A quick fix is to comment out the line,
[navCon release]
But this will introduce a memory leak.

Navigation to another view in iphone

here is my code , i am trying to get from one view to another without any memory leaks.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
firstviewcontroller *first = [[firstviewcontroller alloc] init];
[window addSubview:first.view];
[self.window makeKeyAndVisible];
return YES;
}
-(IBAction)gotosecondview:(id)sender
{
secondviewcontroller *second = [[secondviewcontroller alloc] init];
[self.view addSubview:second.view];
[second release];
}
-(IBAction)gotofirstview:(id)sender
{
[self.view removeFromSuperview];
}
to make the above code work without crashing , all i have to do is remove [second release].
if I remove it I get memory errors (build and analyze) . how can i solve this problem. and i dont want to use [self.navigationController pushViewController:second animated:YES];
all i am trying to do i navigating from one view to another and vice versa WITHOUT using navigation controller. my firstviewcontroller and secondviewcontroller are of type UIViewController.
Thanks in advance.
You need to keep the current view controller alive while its view is showing (so it can process the user input, etc.).
In your code, you can achieve that in several ways:
Keep an instance of firstviewcontroller and secondviewcontroller as instance variables, and release them on the dealloc method.
Keep an instance variable with the currently in use UIViewController and release it when you switch to another view.
The code for the second option would look something like this:
#interface
UIViewController *currentViewController;
#end
#implementation
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
firstviewcontroller *first = [[[firstviewcontroller alloc] init] autorelease];
[self switchToViewController:first];
[self.window makeKeyAndVisible];
return YES;
}
- (void)switchToViewController:(UIViewController *)aViewController {
[currentViewController.view removeFromSuperview];
[currentViewController release];
currentViewController = [aViewController retain];
[self.window addSubview:currentViewController.view];
}
-(IBAction)gotosecondview:(id)sender {
[self switchToViewController:[[[secondviewcontroller alloc] init] autorelease]];
}
#end
Here, all the logic for maintaining a single UIViewController alive lies in the switchToViewController method, which also handles the logic for switching from one view to another. As an added bonus, you can quickly add support for animations by adding a couple of lines in switchToViewController.
You can not release view in the call.
There is only one thing you can do in such conditions. use Autorelease,
The reason [second release] is crashing your code is likely because you're releasing your view controller which in turn releases the second view. The iPhone cookbook has some sample code on switching/swapping views if that's all that you're trying to accomplish. Here's the link. Hope this helps!
link text