I am new to iPhone programming. what I am trying is I have one screen with a button. And I want to change the view controller not only the view when I click that button (I know how to add subview) because from that 2nd view controler, I have to go to the third view which is not possible if I add subview in first place. Can anybody please help me with that? Is this possible? and if yes, how? All the views and view controller are created programmaticaly. I am not using IB.
EDIT: here is the relevant code that fires when clicking button
-(id)showCurrentLoc:(id)sender {
locationController = [currentLocController alloc];
[entry removeFromSuperview];
[newLoc removeFromSuperview];
[currentLoc removeFromSuperview];
[self.view setBackgroundColor:[UIColor clearColor]]; //[self.view addSubview: [locationController view]];
[self.navigationController pushViewController:locationController animated:YES]; [locationController release];
return 0;
} //Location Controller is the tableViewController
Thanks
Vik
You can do something like this
YourViewController *objYourViewController = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
[self.navigationController pushViewController:objYourViewController animated:YES];
[YourViewController release];
Usually, you use a navigation controller for this sort of thing so that the user can easily go back to the previous view. Your view controller would then do something like this:
[self.navigationController pushViewController:someNewViewController animated:YES];
If you want to manage the view controllers yourself, you can always just change the window's rootViewController property. Please read View Controller Programming Guide for the complete picture.
UINavigationController is what you need. It manages a stack of UIViewControllers and if you want to add new UIViewController just push it into this navigation stack. It automates back button behavior for you, and you can pop your current UIViewController from stack whenever you are done with it.
You could work with a UINavigationController. Adding your first UIViewController like this in the init method:
[self setViewControllers:[NSArray arrayWithObject:viewController]];
And then when a button is click or a choice is made, your push the second few controller with (in the first viewController):
[self.navigationController pushViewController:controller animated:YES];
This way you will also get an automatic (back button). Basicly you create a stack of UIViewControllers that you can push and pop like with a normal stack.
I hope this helps. Look into the following:
UINavigationController Class Reference
- (void) loadViewAtIndex:(NSInteger)index {
[self unloadViewAtIndex:activeViewIndex];
switch (index) {
case 1:
{
if (viewController1 == nil)
{
viewController1 = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil];
}
viewController1.view.frame = CGRectMake(0.0, 0.0, viewController1.view.frame.size.width, viewController1.view.frame.size.height);
[window addSubview:viewController1.view];
}
break;
case 2:
{
if (viewController2 == nil)
{
viewController2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
}
viewController2.view.frame = CGRectMake(0.0, 0.0, viewController2.view.frame.size.width, viewController2.view.frame.size.height);
[window addSubview:viewController2.view];
}
break;
default:
break;
}
activeViewIndex = index;
}
- (void) unloadViewAtIndex:(NSInteger)index {
switch (index) {
case 1:
{
if (viewController1 != nil)
{
[viewController1.view removeFromSuperview];
[viewController1 release];
viewController1 = nil;
}
}
break;
case 2:
{
if (viewController2 != nil)
{
[viewController2.view removeFromSuperview];
[viewController2 release];
viewController2 = nil;
}
}
break;
default:
break;
}
}
Related
I have a "FairListViewController". This is the first ViewController. Here by touching a tableCell, I can go to next which is "MenuViewController". And there are two Button, "Product" for "ProductViewController" and "Events" for "EventViewController". I use "NavigationController" as a "rootViewController" in my appDelegate. Now when i touch "Product" button in "MenuViewController" in takes me to "ProductViewController" and touching "BackButton" it smoothly back to "MenuViewController". I did the same code for "ProductViewController", here it takes me to the "EventViewController" but after touching "BackButton", strangely it takes back to First Page which is "FairListViewController". I change the name of my IBAction Button name ( In "EventViewController" nib file) several times & reconnect with nib file, even delete the button from nib file and try with a new button, but the result is same! Can any one similar to this problem before. Any suggestion will be highly appreciable. Thanks a lot in Advance.
Here is my code :
IN MenuViewController (For ProductViewController Button):
- (IBAction)callProductGroups:(id)sender
{
ProductGroupViewController *productGroupViewController;
if(IS_IPHONE_5)
{
productGroupViewController = [[ProductGroupViewController alloc] initWithNibName:#"ProductGroupViewController" bundle:nil];
}
else
{
productGroupViewController = [[ProductGroupViewController alloc] initWithNibName:#"ProductGroupViewControlleriPhone4" bundle:nil];
}
productGroupViewController.topBarImageForAll = self.topBarImageForAll;
productGroupViewController.topBarButtonImageForAll = self.topBarButtonImageForAll;
productGroupViewController.buttonDividerImageForAll = self.buttonDividerImageForAll;
productGroupViewController.backgroundImageForAll = self.backgroundImageForAll;
productGroupViewController.backgroundImageiPhone4ForAll = self.backgroundImageiPhone4ForAll;
[self.navigationController pushViewController:productGroupViewController animated:YES];
}
In ProductViewController :
-(IBAction)goBack:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
In MenuViewController (For EventViewController Button):
- (IBAction)callEvents:(id)sender
{
EventViewController *eventViewController;
if (IS_IPHONE_5)
{
eventViewController=[[EventViewController alloc] initWithNibName:#"EventViewController" bundle:nil];
}
else
{
eventViewController=[[EventViewController alloc] initWithNibName:#"EventViewControlleriPhone4" bundle:nil];
}
eventViewController.topBarImageForAll = self.topBarImageForAll;
eventViewController.topBarButtonImageForAll = self.topBarButtonImageForAll;
eventViewController.buttonDividerImageForAll = self.buttonDividerImageForAll;
eventViewController.backgroundImageForAll = self.backgroundImageForAll;
eventViewController.backgroundImageiPhone4ForAll = self.backgroundImageiPhone4ForAll;
[self.navigationController pushViewController:eventViewController animated:YES];
}
In EvenViewController :
- (IBAction)backButton:(id)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
[There is no problem of Going to next ViewController, the problem is about Coming Back.]
Try instead of
[self.navigationController popToRootViewControllerAnimated:YES];
Use
[self.navigationController popViewControllerAnimated:YES];
Is is possible to have a UIView preloaded so that it will load faster when the user taps on button to load it? Currently I've got a library of informaiton that I'm attempting to load when the user taps a button, and for now it seems to be "ok" , but it makes the navigation to the page choppy, because of all the information in the library it's loading.
Thanks in advance!
It should be possible to split the setup of a View Controller from code that displays the view after a button is pushed. This will eliminate the lag when the button but the task to setup the view controller still need to be done sometime during execution (You can for example put it in the ViewdidAppear method so it is executed while waiting for the button to be pushed.
Take this code for example:
-(IBAction) button_pushed {
/*setup */
NewVC *vc = [[NewVC alloc] init];
vc.var1 = var1;
vc.var2 = x;
[vc setup];
/*display */
[self.navigationController pushViewController:vc animated:NO];
return;
}
You can split the code that setup the view from the code that displays the view
into :
#synthesize vc;
…..
- (NewVC) setup {
//setup
NewVC *vc1 = [[NewVC alloc] init];
vc.var1 = var1;
vc.var2 = x;
[vc setup];
return(vc1);
}
-(void) ViewDidAppear {
if (setupready) {
vc = [self setup];}
return;
}
-(IBAction) button_pushed:(ID) sender {
//display
[self.navigationController pushViewController:vc animated:NO];
return;
}
So I have a settings bar button item in my navigation controller which, when pressed from a home view controller, opens a settings vc transparent view over the home vc, so the home vc is still visible behind the settings vc. I want the nav bar to still show, so in the "HomeViewController.h"I have the following code :
-(IBAction)settingsButtonPressed:(id)sender{
SettingsViewController *settings = [[SettingsViewController alloc]init];
[self.navigationController.view addSubview:settings.view];
}
When I want to remove the settings view, in "SettingsViewController" I tried doing :
-(IBAction)exitSettings:(id)sender{
[self.navigationController.view removeFromSuperview];
}
But when I do this and try to run the program, the program stops, and in the debug area, it just says
Thread 1: EXC_BAD_ACCESS (code = 2, address=0xb0000008)
(lldb)
What am I doing wrong and how can I fix this???
Here crash occurred because of this code:
[self.navigationController.view removeFromSuperview];
You are trying to remove the navigationController view not the settings view.
When you add the SettingsViewController add a tag to it:
-(IBAction)settingsButtonPressed:(id)sender
{
SettingsViewController *settings = [[SettingsViewController alloc]init];
settings.view.tag = 7;
[self.navigationController.view addSubview:settings.view];
}
And use this tag to remove the view from the navigationcontroller:
-(IBAction)exitSettings:(id)sender
{
[[self.navigationController.view viewWithTag:7] removeFromSuperview];
}
for (UIView *view in self.navigationController.view.subviews)
{
if ([view isKindOfClass:[SettingsViewController class]])
{
[view removeFromSuperview];
}
}
-(IBAction)exitSettings:(id)sender
{
[vc dismissModalViewControllerAnimated:YES];
}
vc is your ViewController Object.
try this one.
I'm confused. I have a navigation controller with a BarItem which opens a first view. After some work is done, I want this view to disappear and I want a second view to open.
root view: navigation controller
first view: activity indicator, where some data is put together
second view: MFMailComposeViewController
In the root view, the BarItem runs these lines to open the first view:
IndicatorViewController *indicator = [[IndicatorViewController alloc] initWithNibName:#"IndicatorViewController" bundle:nil];
indicator.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:indicator animated:YES];
The first view (IndicatorViewController) does some work and finally runs
[self dismissModalViewControllerAnimated:YES];
This works fine. But - how do I open the second view?
I tried this:
I open the second view. After closing the second view, my first view pops up again (since it is still there) and get's dismissed at this point. This code is placed in the first view:
- (void) viewDidAppear:(BOOL)animated {
static BOOL firstTime = YES;
if (firstTime) {
//do stuff that takes some time (that's why I show the indicator)
MailViewController *controller = [[MailViewController alloc] init];
if (controller)
[self presentModalViewController:controller animated:YES];
firstTime = NO;
} else {
[self dismissModalViewControllerAnimated:YES];
}
}
Since the first view pops up again, the user can see the indicator one more time, after the second view is closed - and that is not what I want.
What am I missing here? What would be the better way to do this?
I would do something like this. Make a navigationController, and make the first view as the root controller. Then do something like this:
FirstView.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
}
- (void) nextView { // however you get to your next view, button/action/etc.
UIViewController *screen = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
[self.navigationController pushViewController:screen animated:YES];
}
Then in the second view:
SecondView.m
- (void) nextView { // however you get to your next view, button/action/etc.
UIViewController *screen = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
[self.navigationController pushViewController:screen animated:YES];
}
And finally in the rootview:
RootView.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *navStack = [NSArray arrayWithObject:self];
self.navigationController.viewControllers = navStack;
[self.navigationController setNavigationBarHidden:NO];
}
This will make your RootView the new rootview of the NavigationController.
self.navigationController.viewControllers
is the array with all the ViewControllers that are on the navcontrollers stack. The first object is the rootcontroller. If we replace the whole array with our own array, it knows only one item. You CAN go back by dismissing if that's what you want though. This isn't the prettiest way of doing it, but it's not the worst either.
I just want to be able to swipe to a new nib, but am getting stuck. My code builds properly with no errors or warnings, but nothing happens.
Here is my code
- (IBAction) handleSwipeGesture:(UIGestureRecognizer *) sener {
NSLog(#"swipe left");
if(UISwipeGestureRecognizerDirectionLeft) {
SecondDetailViewController *tempController = [[SecondDetailViewController alloc]
initWithNibName:#"SecondDetailView"
bundle:nil];
newController = [tempController retain];
[tempController release];
}
}
The system sees that I am swiping (it gets logged) but it doesn't go to the new nib.
I'm not really married to my code, so if I need to completely rewrite this I'm OK.
Assuming you're handling swipe gesture inside a view controller (and you are using navigation controller), you should do something like this:
- (IBAction)handleSwipeGesture:(UISwipeGestureRecognizer *)sender {
if(sender.direction == UISwipeGestureRecognizerDirectionLeft) {
NSLog(#"swipe left");
SecondDetailViewController *tempController = [[SecondDetailViewController alloc]
initWithNibName:#"SecondDetailView" bundle:nil];
[self.navigationController pushViewController:tempController animated:YES];
[tempController release];
}
}
This line pushes tempController on top of the navigation controller:
[self.navigationController pushViewController:tempController animated:YES];
if you want to present tempController modally, you should call this instead:
[self presentModalViewController:tempController animated:YES];
You are not doing anything with the newController object after you create it. You need to either push it onto your nav controller, present it modally, or grab the view and put it on the screen.