I have an App with one MainWindow.xib file. Then I have ViewControllerA.xib and ViewControllerB.xib. My MainWindow.xib have one ViewController that points two ViewControllerA.xib.
On ViewControllerA I have a button and I would like the button, when pressed, to move ViewControllerB onto the screen. How do I do that?
I tried this code, but I think I am missing something:
- (IBAction)btMyButton:(id)sender
{
ViewControllerB * viewController = [[ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:nil];
[[UIApplication sharedApplication].keyWindow addSubview:viewController.view];
[self.navigationController pushViewController:viewController animated:YES];
}
My ViewControllerB does appear, but it is squashed at the top of the screen, over the previous view. Any help is greatly appreciated.
Thank you
Remove the second line:
[[UIApplication sharedApplication].keyWindow addSubview:viewController.view];
You are adding the view twice. The 2nd and 3rd lines both cause the view to be added to the view hierarchy in different places.
--update--
If you remove the 2nd line and are not seeing your view then self.navigationController is most likely nil. Try [self presentModalViewController:] instead.
Make sure that the view of controller B has correct hight you should subtract the navigation bar height 44 px and status bar 20 px as well. Those values are for iPhone.
- (IBAction)btMyButton:(id)sender
{
//you should load from the main app bundle
ViewControllerB * viewController = [[ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:[NSBundle mainBundle]];
// you don't need the following line
//[[UIApplication sharedApplication].keyWindow addSubview:viewController.view];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
Update
As the above comment says if you may don't have a navigation controller to push Controller B into. So Add a navigation controller into the main window instead of the view controller and make its root view controller you Controller A.
I hope this helps you,
you will need to remove old viewcontroller from main windows.
- (IBAction)btMyButton:(id)sender
{
//Assuming you declare two Iboutlet controllerA, controllerB mapping with that view as class variable
{
if (self.controllerB == nil)
{
ViewControllerB * viewController = [[ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:nil];
self.controllerB = viewController;
[viewController release];
}
[controllerA.view removeFromSuperview];
[self.view insertSubview:controllerB.view atIndex:0];
}
}
Related
I'm trying to do a switch view. My first view is a storyboard and i want to switch for view2, i have no problem when click the botton in my first view everything is fine. The prolem is when i am trying to go back, the screen is going black and is not going back to the first view. Here the code that i'm using.
ViewController.h
- (IBAction)View2:(id)sender;
ViewController.m
- (IBAction)View2:(id)sender {
View2 *second = [[View2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
}
And here the code that i am using to go back from the second view to the first.
view2.h
- (IBAction)back:(id)sender;
View2.m
- (IBAction)back:(id)sender {
ViewController *second = [[ViewController2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
}
Am I doing some kind of error?
Thanks
Your issue is in View2.m
- (IBAction)back:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
should do the trick
Apple has a View Controller Programming Guide that I suggest skimming through
UPDATE
If you need to jump back more that one ViewController, you should use NSNotificationCenter or keep a reference to the viewController you need to jump back to.
In my experiences, the following line does 1 of 2 things (where self is a subclass of UIViewController)
[self dismissModalViewControllerAnimated:YES];
1) If self has presented another view controller, the line above will dismiss all view controllers that have been presented on top of self
2) If self has not presented any other view controller, the line above will dismiss self back to the previous view controller
I have an iPad app that uses the storyboard board feature and then I have a separate .xib file for another view. I can switch to the separate view and its fine:
-(IBAction)SecondView:(id)sender{
SecondView *Second = [[SecondView alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:Second animated:NO];
}
But when I am in the Second View and try going back I do everything the same just with the first view controller, but It just goes to a black screen:
-(IBAction)FirstView:(id)sender{
FirstView *First = [[FirstView alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:First animated:NO];
}
What do you guys think? Am I doing something wrong? What is the best way to switch views?
initWithNibName:bundle is for loading nib or xib files.
If you are loading from a storyboard, you need to use
FirstView *First= [self.storyboard instantiateViewControllerWithIdentifier:#"IDENTIFIER"];
IDENTIFIER is defined in your storyboard, it's in the Utilities, Attributes Inspector on the right side.
HOWEVER your real problem is that you shouldn't be loading from the storyboard at all. you should just be calling
[self dismissModalViewControllerAnimated:YES];
That call will clean up the presentModalViewController:animated: that you used to put the modal view controller up in the first place.
You presented SecondView using presentModalViewController:animated:, so you need to dismiss it using dismissModalViewControllerAnimated:.
- (IBAction)FirstView:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
When I push cancel button in the third view, I want to go back to the first view directly.
I also want to remove the second view.
How can I do that?
This is the code.
// this part is in the first view.
self.second = [SecondController alloc] init];
[self.view addSubview:second.view];
// this part is in the second view.
ThirdController *thirdController = [[ThirdController alloc] initWithStyle:UITableViewStyleGrouped];
self.navigationController = [UINavigationController alloc] initWithRootViewController:thirdController];
[self.view addSubview:navigationController.view];
// this part is in the third view.
- (void)cancel {
[self.view removeFromSuperview]; // this only goes to the second view.
}
EDIT:
Can I use popToViewController in called contoller? My app crashes.
I thought popToViewController can be used only in calling controller.
And popToViewController is used when it was pushed.
I did add not push.
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:0] animated:YES];
popToViewController:animated: is a UINavigationController method that you use when popping view controllers off the navigation controller stack. It doesn't fit for this scenario.
This user is adding subviews, not pushing them on a navigation controller stack.
As a note, it appears as a matter of design you should be using a navigation controller with the first view as the root controller, then the second pushed on the stack, and the third pushed on the stack. Then all you have to do is [self.navigationController popToRootViewControllerAnimated:YES].
I think this will work if you want to keep your current architecture:
// this part is in the third view.
- (void)cancel {
// remove the second view (self.view.superview) from the first view
[self.view.superview removeFromSuperView];
// can't recall, possibly you still need to remove the third view, but i think removing the superview will do it.
// [self.view removeFromSuperView];
}
If you prefer to try the UINavigationController route, then the easiest path is to create a new project in Xcode and select the type for a Navigation-Based Application or a Master-Detail Application. This will create a UINavigationController in a nib and add it to your window. You can then set the root view controller in Interface Builder to your FirstViewController class.
If you prefer to create the UINavigationController in code, then that is also possible. I show that below, along with the rest of the code you need, regardless of whether you create your UINavigationController in a nib in IB or in code.
I also recommend reading the View Controller Programming Guide for iOS.
In your app delegate or some other code:
-(void)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions [
// I would recommend setting up the UINavigationController and FirstViewController as IBOutlets in your nib, but it can be done in code.
FirstViewController* fvc = [[FirstViewController alloc] initWithNibName:#"FirstView" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:fvc];
[window addSubView:navController.view];
[window makeKeyAndVisible];
[fvc release];
[navController release];
}
In the first view controller:
SecondViewController* svc = [[SecondViewController alloc] initWithNibName:#"SecondView" bundle:nil];
[self.navigationController pushViewController:svc animated:YES];
[svc release];
In the second view controller:
ThirdViewController* tvc = [[ThirdViewController alloc] initWithNibName:#"ThirdView" bundle:nil];
[self.navigationController pushViewController:tvc animated:YES];
[tvc release];
In the third view controller:
-(void)cancel {
// returns to the first view controller
[self.navigationController popToRootViewControllerAnimated:YES];
}
Use
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
to go back to a specific view controller.
Try this:
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
This will pop to the view at index 1. Hope that Helps!
// this part is in the third view.
- (void)cancel {
self.first = [SecondController alloc] init];
[self.view addSubview:second.view];
}
And I think if you have you don't need to be worried about removing beneath view, later these will removed.
I'm extremly new to iphone and I have the following misunderstanding.
All over internet the tutorials about how to use NavigationController programatically it says:
NavigationController must be declared in applicationDidFinishLaunching and must be init with a root.After that you can add views to it.
I have this:
A UIViewController class meaning(AdiViewController.h, AdiViewController.m and AdiViewController.xib) and no Delegate file meaning no applicationDidFinishLaunching method.
What I wanna do is from my class-AdiViewController when pressing a button to go to another view.
I understand that I need a NavigationController which should retain my views having the root AdiViewController.
But my problem is where should I initializate that NavigationController in viewDidAppear??...cause I don't have the Delegate files.
If you could provide a minimal example with this small issue of mine it would be great.I'm sure that for those how are senior this is nothing but still I don't get it.Thanks
NavigationController must be declared in applicationDidFinishLaunching -> this is not true.
In your AdiViewController if you have button when you push that button you want to load navigation Controller right ?
// Hook this IBAction to your button in AdiViewController
- (IBAction)pushNavController
{
AnotherViewController* rootView = [[AnotherViewController alloc] initWithNibName:#"Anotherview" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:rootView];
[rootView release];
[self presentModalViewController:navController animated:YES];
[navController release];
}
If you are in AnotherViewController i.e., you are in root view controller of Navigation controller. You need to push and pop view controllers from there. For example if you have a button in AnotherViewController:
// push next view controller onto navigation controller's stack
- (IBAction)pushNextViewController
{
NextViewController* nextView = [[NextViewController alloc] initWithNibName:#"NextView" bundle:nil];
[self.navigationController pushViewController:nextView animated:YES];
[nextView release];
}
// Similarly if you want to go back to AnotherViewController from NextViewController you just pop that from navigation controller's stack
- (IBAction)pushNextViewController
{
[self.navigationController popViewControllerAnimated:YES];
}
here's my code:
ViewController *vc = [[ViewController alloc] initWithNibName:#"TableView" bundle:nil];
[self.navigationController presentModalViewController:vc animated:YES];
//[self setView:[vc view]];
If I call it, nothing happens. However, if I change it to:
ViewController *vc = [[ViewController alloc] initWithNibName:#"TableView" bundle:nil];
//[self.navigationController presentModalViewController:vc animated:YES];
[self setView:[vc view]];
The view appears just fine (without the transition, of course).
What am I doing wrong? Is there anything special you have to take care of when initializing the view controller? I tried to copy as much as possible from Apple's examples, but I can't get this to work...
Thanks for any input!
-- Ry
You can only present modal view controllers from controllers that have already been shown onscreen (usually through a UINavigationController or UITabBarController). Try creating a UINavigationController, pushing a viewController to it, and then presenting your modal controller. There's a starter project in Xcode that shows how to create a UINavigationController-based flow if you're unfamiliar with it.
One other thing to note: if you haven't pushed the view controller onto a UINavigationController, the .navigationController property will be nil, and messaging it will have no effect.
I encountered the same problem while attempting to show a modal view over another modal view. Ben's answer is correct, and can be implemented like so:
#interface FirstView: UIViewController {
UIViewController *firstView;
}
- (IBAction)showOptionsView:(id)sender;
#end
In the main view class:
- (void)viewDidLoad {
[super viewDidLoad];
firstView = [[UIViewController alloc]init];
[firstView setView:self.view];
[firstView setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
}
- (IBAction)showOptionsView:(id)sender {
OptionsView *optView = [[OptionsView alloc]initWithNibName:#"OptionsView" bundle:nil];
if(firstView != nil) {
[firstView presentModalViewController:optView animated:YES];
[optView release];
}