I have the following code in my AppDelegate:
#import <UIKit/UIKit.h>
#class PersonalDiarySystemViewController;
#interface PersonalDiarySystemAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
PersonalDiarySystemViewController *viewController;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet PersonalDiarySystemViewController *viewController;
#property (nonatomic, retain) UINavigationController *navigationController;
#end
#import "PersonalDiarySystemAppDelegate.h"
#import "PersonalDiarySystemViewController.h"
#implementation PersonalDiarySystemAppDelegate
#synthesize window;
#synthesize viewController;
#synthesize navigationController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Set the view controller as the window's root view controller and display.
self.window.rootViewController = self.viewController;
navigationController = [[UINavigationController alloc] initWithRootViewController:self.window.rootViewController];
navigationController.navigationBar.tintColor = [UIColor
colorWithRed:217.0/255
green:33.0/255
blue:0
alpha:1];
navigationController.navigationBarHidden = YES;
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
My rootviewcontroller tries to load another viewcontroller into the navigation controllers stack in its viewDidLoad method but for some reason the view is not getting pushed:
-(void) viewDidLoad{
lvc = [[LoginViewController alloc] init];
//lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[lvc setDelegate:self];
//[self presentModalViewController:lvc animated:YES];
[self.navigationController pushViewController:lvc animated:YES];
}
I'm getting no errors so not sure whats going on...using presentModalViewController works...so really am confused!!
You need to assign lvc to LoginViewController.
- (void) viewDidAppear
{
[self performSelector:#selector(loginCheck:) withObject:nil afterDelay:0.5];
}
- (void) loginCheck:(id)sender
{
LoginViewController * lvc = [[LoginViewController alloc] init];
//lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[lvc setDelegate:self];
//[self presentModalViewController:lvc animated:YES];
[self.navigationController pushViewController:lvc animated:YES];
}
Put your
[self.navigationController pushViewController:loginViewController];
Into the
- (void)viewDidAppear:(BOOL)animated
method. The viewControllers navigationController doesn't get loaded until then
There are two things that might go wrong.
First, you alloc the navigation controller in applicationDidFinishLaunching, I'm not quite sure which goes first, applicationDidFinishLaunching or viewDidLoad.
As you've seen, you first set your root view controller, then alloc the navigation controller, then maybe viewDidLoad launched right after you set the root view controller, then the navigation controller is allocated. so the words in viewDidLoad may not work because at that time, the navigation controller hasn't been born yet.
But I don't' quite thing the previous explanation works. it's just a possibility.
There's another strange thing, you set the navigation bar of your navigation controller hidden
navigationController.navigationBarHidden = YES;
Then it seems that the user can't pop back to the root view controller, so the navigation controller don't push the login view controller.
Meanwhile, the modal view controller can be dismissed with the navigation bar hidden or the navigation bar not allocated, so it works when you present it as a modal view controller.
but i'm still not quite sure about it since i'm now having some issues with Xcode, so i can't test the previous two ideas, sorry about that. but i still recommend that you set navigationBarHidden to NO.
- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.navController = navigationController;
[mainViewController release];
[navigationController release];
// Configure and display the window.
[window addSubview:navController.view];
[window makeKeyAndVisible];
}
- (void)viewDidLoad{
lvc = [[LoginViewController alloc] init];
[self.navigationController pushViewController:lvc animated:YES];
}
Related
May somebody let me know:
How to navigate from one view to another view in single viewcontroller in iphone sdk? I have an application in which i want to push to next view and pop to previous view in a single View controller. How this functionality can be achieved?
Thanks in advance
You can add and remove your secondview.Like this to navigate
-(IBAction)navigate:(id)sender
{
[self.view addSubView:secondView];
}
and this one to po to first view
-(IBAction)popToFirstView:(id)sender
{
[secondView removeFromSuperView];
}
Note:- You can use animations for adding and removing view, if you want to give animated effects.
If you need a single view controller you can try using a UIScrollView, that contain the 2 view, and a button to scroll from a view to another... but if i can give a tip, it's better using 2 view controller and a navigation view controller
You need to use UINavigation Controller to get push and pop.
do this way
In AppDelegate.h file
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
//this will be your first screen
#property (strong, nonatomic) FavViewController *favViewController;
#end
In A*ppDelegate.m* file
#import "AppDelegate.h"
#import "FavViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize favViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//initialize view controller
favViewController = [[FavViewController alloc] initWithNibName:#"FavViewController" bundle:nil];
//add navigation controller
UINavigationController *favouriteView = [[UINavigationController alloc] initWithRootViewController:favViewController];
//add controller to witndow
self.window.rootViewController = favouriteView;
[self.window makeKeyAndVisible];
return YES;
}
#end
Now come to the UIViewController, where you want to load/push to new controller
to load/push to new controller use this code
//this will be next screen
DetailsViewController *detailsViewController = [[DetailsViewController alloc ]init];
[self.navigationController pushViewController:detailsViewController animated:YES];
to go back or pop controller use this
//now it will send back to parent screen
[self.navigationController popViewControllerAnimated:YES];
I have figured out the solution for this problem and here is the solution as below:-
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UIButton *backbtn;
IBOutlet UIButton *nxtBtn;
IBOutlet UILabel *label;
}
-(IBAction)nxt:(id)sender;
-(IBAction)ba:(id)sender;
#end
#import "ViewController.h"
#interface ViewController ()
#end
int count=0;
#implementation ViewController
- (void)viewDidLoad
{
label.text=[[NSUserDefaults standardUserDefaults] objectForKey:#"NavigtionNumber"];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
-(IBAction)nxt:(id)sender
{
count++;
label.text=[NSString stringWithFormat:#" navigation time %d",count];
[[NSUserDefaults standardUserDefaults] setObject:label.text forKey:#"NavigtionNumber"];
[[NSUserDefaults standardUserDefaults] synchronize];
ViewController *vc=[[ViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
-(IBAction)ba:(id)sender
{
count--;
label.text=[NSString stringWithFormat:#" navigation time %d",count];
[[NSUserDefaults standardUserDefaults] setObject:label.text forKey:#"NavigtionNumber"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.navigationController popViewControllerAnimated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Hope this will help others in future.
Thanks.
I wanted to add a navigation controller to a view based application . how can we do this both programmatically and using xib file..
If you need to incorporate a navigation controller in your uiviewcontroller you need to initialize it as it follows
UIViewController *yourViewController = ...
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:yourViewController];
[self presentModalViewController:navController animated:YES];
//you need to release the controller
[navController release];
If you are in the UIApplicationDelegate method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
You can't do a presentModalViewController:navController animated... then you need to add the navController.view to the window
UIViewController *yourViewController = ...
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:yourViewController];
[self.window addSubview:navController.view];
//don't do a release of navController because is not retained by addSubview
UINavigationController *navcontroller = [[UINavigationController alloc] initWithRootViewController:viewController];//here viewController is to which you want to make the navigation
[self.view addSubView:navController.view];
You can just drag a "Navigation Bar" from your objects in the bottom right corner of Interface Builder. This basically does what Sachin says in his answer but you still have to programmatically create the functionality of the navigation controller. I.e pushing new views to the stack and poping them off.
In my opinion it's easiest to do it entierly in the code.
If you want to have a navigation controller as the root view for your main window. Then you can do so by using the following code.
#interface yourAppDelegate_iPad : NSObject <UIApplicationDelegate> {
UINavigationController *navigationController;
}
#property (nonatomic, retain) UINavigationController *navigationController;
#end
#implementation yourAppDelegate
#synthesize navigationController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
navigationController = [[UINavigationController alloc] initWithRootViewController:yourRootViewController];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
You can do this by using the xib as follows
Open the MainWindow.xib
Drag and drop a UINavigationController to it.
Create and connect the outlets.
Open attributes for the navigation controller and set the root
view.
I have a root view controller which should load another view controller as soon as it is done loading (i.e. in the viewDidLoad method).
I am using the UINavigationController in order to push a new view controller onto the stack:
In my rootviewcontrollerappdelegate:
-(void) viewDidLoad{
LoginViewController* lvc = [[LoginViewController alloc]init];
[self.navigationController pushViewController:lvc animated:NO];
}
I have textfields and buttons in the view controller to be loaded. The above doesn't seem to work however...It loads just a blank grey screen and no UINavigation bar is present. If I comment out the second line (pushViewController line), then I see the navigation bar. So I think it is loading something, but the items in the view controller being loaded are not being shown...Any ideas why?
Check if navigationController is pointing to nil. If it does, try
[self.view addSubview:self.pushViewController.view]
I had the same problem and found the above solution here:
UIViewController -viewDidLoad not being called
Unless you're doing something tricky, you should be calling alloc on the LoginViewController class rather than a variable. Also, if you've set up LoginViewController in Interface Builder (as opposed to programmatically), you'll need to load it from an NIB:
LoginViewController *lvc = [[[LoginViewController alloc] initWithNibName:nil bundle:nil] autorelease];
[self.navigationController pushViewController:lvc animated:NO];
Have a look at initWithNibName:bundle: in the docs.
Not entirely sure what you are trying to achieve but when you instantiate LoginViewContoller it should probably look like this
LoginViewController* lvc = [[LoginViewController alloc]init];
Judging by the nature of your naming for your view controller, is your LoginViewController the first view controller for your UINavigationController?
If that is what you're trying to do, you should instead initialise your navigation controller with the LoginViewController as the root controller instead of pushing it onto the navigation stack.
UINavigationController has a method to do this:
- (id)initWithRootViewController:(UIViewController *)rootViewController
EDIT:
Well, one way you can go about it is like this.
In your application delegate .h file, you should have declared a UINavigationController.
#interface MyAppDelegate : NSObject <UIApplicationDelegate>
{
UINavigationController *navController;
}
#property (nonatomic, retain) UINavigationController *navController;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
In your App Delegate didFinishLaunching:withOption: you can create an instance of your LoginViewController there, and use that to init your UINavigation controller as the root view controller
#import "LoginViewController.h"
#implementation MyAppDelegate
#synthesize navController;
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
LoginViewController *loginController = [[LoginViewController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:loginController];
[loginController release];
[[self window] setRootViewController:navController];
[navController release];
[self.window makeKeyAndVisible];
return YES;
}
I probably have a typo here or there but that's one way I would go about doing it.
I'm going mad using navigation controllers on the iPhone.
I have an app, with a main xib (the one with the window) inside wich I have put a NavigationController, inside wich I have a viewController. Everything is connected and the ViewController is defined with the correct inherited class name.
In the didFinishLaunchingWithOptions, i have :
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
In the .h I have :
#interface MainAppDelegate : NSObject <UIApplicationDelegate> {
IBOutlet UIWindow *window;
IBOutlet UINavigationController* navigationController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) UINavigationController* navigationController;
#end
Then in the First ViewController I have a button connected to this method :
- (IBAction) definePreferences:(id)sender {
PreferencesController *nextWindow = [[[PreferencesController alloc] initWithNibName:#"Preferences" bundle:nil] autorelease];
UINavigationController* navController = [[[UINavigationController alloc] initWithRootViewController:nextWindow] autorelease];
[self.navigationController presentModalViewController:navController animated:YES];
}
all items in the main xib seems to be connected... and retained by the properties. The AppDelegate with its window and navigationController... the Window rootviewcontroller with the same navigationController... and the file owner with the app delegate...
Everything runs fine, but the preferences window never appears...
Can you see why ?
If needed, I must say that this first view controller makes the camera interface appear and put an overlay over it. The button is onto this overlay. The imagePicker is show like this in viewDidAppear :
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
[self presentModalViewController:picker animated:YES];
[picker release];
EDIT :
In viewDidAppear, self.navigationController is ok at the start and end of method.
In definePreferences, self.navigationController is nil. Nothing is called beetween those two calls.
Nothing
EDIT :
The problem may come from the way I init the viewController on which the button is.
Here is the method called from the firstView called by the Navigation Controller.
- (void) viewDidAppear:(BOOL)animated {
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
// Set the image picker source:
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls = NO;
picker.navigationBarHidden = YES;
picker.wantsFullScreenLayout = YES;
// Insert the overlay
OverlayViewController* overlayController = [[OverlayViewController alloc] initWithNibName:#"Overlay" bundle:nil];
picker.cameraOverlayView = overlayController.view;
// Show the picker:
[self presentModalViewController:picker animated:NO];
[picker release];
[super viewDidAppear:YES];
}
But... how should I do ?
First, never call an IBAction setPreferences:. That violates KVC, and can eventually cause all kinds of bizarre behaviors. setX: is a reserved name for the setter of the property named x.
You should not be creating a nav controller in this method (i.e. navController). You should be using the one you created in the NIB (self.navigationController). Check if that is nil. If it is, then you either didn't set up a navigation controller in the NIB, or you didn't wire it to this view controller.
You should also verify that nextWindow is non-nil.
I've finaly solved the problem.
See https://stackoverflow.com/questions/5317968/iphone-camera-overlay-going-down-after-a-modal-view-transition
I have some hair less... :-)
I'm attempting to switch views with an iPhone application- I have a parent view controller, SuperviewController, and then two views that I want to switch within that parent view, MainMenuController and MainGameController.
*EDIT*: I am now using navigation controllers:
SuperviewController.m
viewDidLoad
self.mainMenuController = [[MainMenuController alloc] initWithNibName:#"MainMenu" bundle:nil];
[[self navigationController] pushViewController:self.mainMenuController animated:NO];
switchToMainGame
self.mainGameController = [[MainGameController alloc] initWithNibName:#"MainGame" bundle:nil];
[[self navigationController] pushViewController:self.mainGameController animated:NO];
The app loads correctly with the mainMenu.xib. However, when calling switchToMainGame, nothing happens- it's as if XCode forgot what mainGameController is.
Thanks for any help.
You might consider swapping view controllers not views, using UINavigationController.
In your AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
And in -[AppDelegate applicationDidFinishLaunching:] instantiate navigationController, thus:
[self setNavigationController:[[UINavigationController alloc] initWithRootViewController:mySuperviewController]];
[[self navigationController] setNavigationBarHidden:YES];
// Configure and show the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
Then within SuperviewController.m you can instantiate your MainMenuController and MainGameController, as you already do. To start with MainMenuController you could do this in SuperviewController -viewDidLoad
[[self navigationController] pushViewController:[self mainMenuController] animated:YES];
You would need to add some smarts to switch directly between mainMenuController and mainGameController - but it wouldn't be difficult.
So as not to reload nibs again and again, consider defining accessor methods like this:
- (MainGameController*) mainGameController
{
if (mainGameController == nil)
{
mainGameController = [[MainGameController alloc] initWithNibName:#"MainGame" bundle:nil];
}
return mainGameController;
}
Also, bear in mind that switching between sibling view controllers involve popping current view controller (e.g., mainMenuController) before pushing other view controller (e.g., mainGameController).