How to change first simple singleview viewController to navigation viewController? - iphone

I first like to load simple viewController which shows some option and then clicking on some button I would like to load navigationController or tabbarController depending on button click. How can I do this ?

I replace the root view controller on the window when I want to switch the views.
For example in my app I show a loading screen first then I switch the view to a login screen.
To do this you need a reference to your app delegate then you can access the window property and replace the root view controller:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
LoginViewController *loginVC = [[LoginViewController alloc] init];
appDelegate.window.rootViewController = loginVC;

In your simpleViewController :
- (IBAction) yourButtonAction:(id)sender
{
UIViewController *Vc = [[theViewControllerYouWantToShow alloc]init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:Vc];
[self presentModalViewController:nav animated:YES];
}
Edit :
you have three options to show your viewController content :
as the example above using presentModalViewController:
add the viewController view as a subView to the current viewController.
in your case : [simpleViewController.view addSubView:nav.view];
3.or if your simple ViewController is the navigation root viewController you can push other viewControllers to its navigation stack.

in appdelegate.h
#property (strong, nonatomic) id<UIApplicationDelegate>delegate;
in appdelgate.m
#synthesize delegate;
in my first viewController's .h file
AppDelegate *myappDelegate;
-(IBAction)start:(id)sender;
in my first viewController's .m file
-(IBAction)start:(id)sender
{
NSLog(#"Start Button is clicked");
mvc = [[MasterViewController alloc]initWithNibName:#"MasterViewController" bundle:nil];
myappDelegate = [[UIApplication sharedApplication]delegate];
myappDelegate.navigationController = [[UINavigationController alloc]initWithRootViewController:mvc];
myappDelegate.window.rootViewController = myappDelegate.navigationController;
[myappDelegate.window makeKeyAndVisible];
}

Related

Not able to get Current ViewController inside applicationWillResignActive

I have a storyboard based Single View App;
I have 3 ViewControllers on my Storyboard linked to 3 ViewController classes in the code;
I browse between ViewControllers by doing this:
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
MenuViewController* mainMenu = [sb instantiateViewControllerWithIdentifier:#"vcMainMenu"];
mainMenu.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:mainMenu animated:YES];
Now I need to access different UIcontrols on the applicationWillResignActive from the current active ViewController, I will access different controls depending of the ViewController, I'm trying to accomplish this by doing:
if ([self.window.rootViewController isKindOfClass:[LowProfileViewController class]])
{
NSLog(#"here!");
}
But it always returns the rootViewController. How Can I get the current displayed rootViewController from applicationWillResignActive?
Please, Incorporate NavigationController is not an option...
thanks
You could try this -
Make An AppDelegate #property (i.e. currentModelViewController)
#property (nonatomic, retain) UIViewController *currentModelViewController;
For each ViewControllers in viewDidAppear or in viewWillAppear
appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.currentModelViewController = self;
Now this will work
if ([self.currentModelViewController isKindOfClass:[LowProfileViewController class]])
{
NSLog(#"here!");
}

How to get navController from AppDelegate.

I am wondering, that how to get navController from AppDelegate = [[UIApplication sharedApplication] delegate] in the iPhone programming. e.g., in other viewController where we reference to the AppDelegate.
In the applicationDelegate.h we have:
UINavigationController *navController;
And the following in applicationDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview: navController.view];
[window makeKeyAndVisible];
}
Is there anyway to get the navController from the mainWindow:
UIWindow *mainWindow = [appDelegate window];
If this other UIViewController is contained in the UINavigationController, you can simply call:
UINavigationController *navController = self.navigationController;
from the UIViewController.
Otherwise, you can set UINavigationController as a property in the AppDelegate.
// AppDelegate.h
#property (nonatomic, strong) UINavigationController *navController;
Then access appDelegate.navController.
Or, you can set the UINavigationController as window's rootViewController:
[window setRootViewController:navController];
And call from anywhere:
UINavigationController *navController = window.rootViewController;
You can make the navController a property
#property (nonatomic,strong) UINavigationController *navController;
Then just access it from your appdelegate
appDelegate.Controller
You can make the navController as a property of your delegate class. sample below:
In applicationDelegate.h
#property (retain, nonatomic) UINavigationController *navController;
In applicationDelegate.m
#synthesize navController;
then you can use the following code to get the navController in other classes (Assume your delegate class is MyApplicationDelegate):
appDelegate = (MyApplicationDelegate*)[[UIApplication sharedApplication] delegate];
UINavigationController *navController = appDeleagte.navController
No extra properties needed, available almost anywhere in your application using this macro definition:
#define mainNavController (((AppDelegate*)[[UIApplication sharedApplication] delegate]).navController)
When you put the macro at the top of your source or in a .h header file that you import into your source, then you can start using mainNavController as if it were a local variable.
For example:
[mainNavController pushViewController:myViewController animated:YES];
Or without the macro, directly in code:
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.navController; // do something with the navController
You can use this code almost anywhere, which is handy if you're working inside a class and you can't access a ViewController directly.
If you are beginer and learner, the navigation controller is shared in whole application which will just prepare the "stack" of your app's viewcontrollers, so you can access the navigationcontroller in any viewcontroller(Only if that controller has been pushed) through out the app. When you push any controller it will added to the "stack" of navigation controller.
You can access the navigation controller with the self object of that viewcontroller itself.
[self.navigationController pushViewController:detail animated:YES];
Go through with the link will give complete knowledge of navigation anatomy.
http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html

iPhone - pushViewController Issue

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.

How to access custom UIViewController in a UISplitViewController from another class

I have a custom customUIViewController in a UISplitViewController and want to access the instance of the customUiViewController from the detailView (which is another UIViewController inside the UISplitViewController) from another class; how can I do this?
CODE SNIP (Dont worry about the syntax; it is shorten up)
myAppDelegate.m
customViewController *masterView = [[customViewController alloc] init;
UINavigationController *NVC = [[UINavigationController alloc] initWithRootViewController:masterView];
MYViewController *detailView = [[MyViewController alloc] init;
UISplitViewController *mySplit = [...];
mySplit.viewControllers = NSArray[...masterview,detailView,nil];
[window addSubView:mySplit view];
MyViewController.m
-(void) someMethod {
customViewController *myInstance = (customViewController)[self.splitViewController objectAtIndex:0]; ??
// I think this just gets the outter UINavigationController
[myInstance doSomething];
}
customViewController.m
-(void) doSomething {
}
I want to be able to get access to customViewController to call the doSomething method. Both customViewController and myViewController is inside the same UISplitViewController
UIViewControllers have a splitViewController property so try using that to get a reference:
customViewController *myInstance =
(customViewController *)[self.splitViewController.viewControllers
objectAtIndex:0];
Index 0 is the left-side view controller in the split view controller.
Edit:
If the left-side view controller is a UINavigationController, then to get the root view controller of that, do this:
UINavigationController *nc =
(UINavigationController *)[self.splitViewController.viewControllers
objectAtIndex:0];
customViewController *myInstance =
(customViewController *)[nc.viewControllers objectAtIndex:0];
If you're working with the default UISplitView that XCode makes, you need to reference the AppDelegate to get the splitView's ivar:
YourAppDelegate *del = (YourAppDelegate *)[[UIApplication sharedApplication]delegate];
UISplitViewController *split = del.splitViewController;
NSArray *vcArray = split.viewControllers;
//left is objectAtIndex:0, right is objectAtIndex:1

Use modal view as "normal" view

I want to use a modal view (UIViewController) as a "normal" view, which can be pushed on the navigation controller stack. Normally, a modal view is presented like this:
LoginViewController *myView = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myView];
[self.navigationController presentModalViewController:navController animated:YES];
[myView release];
myView = nil;
[navController release];
navController = nil;
But I want to do something like this:
[[self navigationController] pushViewController:myView animated:YES];
The problem is that my modal view has a right and a left button. So I would have to check how the view is loaded and present the buttons in another way. The idea behind this is to have the back button. So I can use the same modal view a few times.
Edit:
#petert:
Now I followed your example. My issue is that I'm using a UINavigationBar for the modal view. To get this UINavigationBar I create a navigation controller. I'm using the navigation bar because I have my buttons in it. So checking if parentViewController is of type UINavigationController does not work for me. I'm always getting a modal view. Here is how I do it:
// load modal view
MyViewController *myView = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myView];
[[self navigationController] presentModalViewController:navController animated:YES];
[navController release];
navController = nil;
[myView release];
myView = nil;
// load as normal view
MyViewController *myView = [[MyViewController alloc] init];
[[self navigationController] pushViewController:myView animated:YES];
Good tips in this StackOverflow answer.
I prefer to use UIViewController's property:
#property(nonatomic, readonly) UIViewController *parentViewController
in a view controller's subclass:
Look at the value of the controller's parentViewController property. If it's an instance of UINavigationController, then you're in the navigation stack. If you're being displayed modally, it'll be an instance of your last view controller.
So in -viewDidLoad for example:
- (void)viewDidLoad
{
if ([self.parentViewController isKindOfClass:[UINavigationController class]])
{
// navigation controller
self.title = #"...";
}
else
{
// modal
self.title = #"Modal";
// add cancel and done buttons now...
}
}
Or, a pretty simple solution would be to customize your init method to your MyViewController class to encode your intent for the view controller.
Add the following to the MyViewController header:
#interface MyViewController : UIViewController
{
BOOL modal;
}
- (id)initForModal:(BOOL)isModal;
#end
Now in the implementation file:
#interface MyViewController ()
#property (nonatomic) BOOL modal;
#end
#implementation MyViewController
#synthesize modal;
- (id)initForModal:(BOOL)isModal;
{
if (self = [super initWithNibName:#"MyViewController" bundle:nil])
{
self.modal = isModal;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.modal)
{
// add cancel and done buttons …
}
else
{
// assuming we're presented from a navigation view …
}
}
Now to use this modally:
// load modal view
MyViewController *myView = [[MyViewController alloc] initForModal:YES];
Or not modally:
// load as normal view
MyViewController *myView = [[MyViewController alloc] initForModal:NO];
I'm assuming you're creating the view controller(s) from NIBs, but as always see the View Controller Progamming Guide for iOS and especially the section titled "Defining a Custom View Controller Class".
For clarification: myView isn't modal. You just present it as a modal one.
If you just push it into a UINavigationController hierarchy it will behave like a "normal" one.
You can't push the same view controller onto the navigation stack several times. Just once.
Also see this for how to customize the view:
SO modal question