I'm new to iOS development.
I have a ViewController ViewController with a button. When the user presses that button, I want to switch the view to RegisterViewController.
ViewController.m contains following code:
#import "ViewController.h"
#import "RegisterViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize registerViewButton;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)registerViewButtonClick:(id)sender {
NSLog(#"registerViewButtonClick called");
RegisterViewController* controller = [[RegisterViewController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
}
#end
According the debug output, method registerViewButtonClick is actually called, when I press the button.
But the view represented by RegisterViewController doesn't appear.
The code of the application is available here.
What do I need to change in order for the RegisterViewController's view to become visible, when the button is pressed?
I ran your code and found that there is no navigation controller implemented in your code but you are trying to push the registerViewController. Try to present the viewcontroller like below:
[self presentViewController:controller animated:YES completion:nil];
instead of
[self.navigationController pushViewController:controller animated:YES];
The pushViewController works only when there is a UINavigationController. As per the documentation, The UINavigationController class implements a specialized view controller that manages the navigation of hierarchical content. Since, there is no UINavigationController in your code (self.navigationController is nil in this case), nothing happens when you try to push the viewController.
UINavigationController also comes handy when you want to maintain a stack of viewControllers wherein you can push or pop as per the need. This also gives you 'Back' button automatically. If your need is just to present a viewcontroller, then presentViewController: can be the right option.
If you want to present then no need of UINavigationalController.
But for pushing UINavigationalController is must .
In Storyboard, you have to add one UINavigationalController.
In Button Actions initialise the VC correctly with nib Name.
RegisterViewController* controller = [[RegisterViewController alloc] initWithNibName:#"RegisterViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
You might need to initialize the UIViewController with the nib name..
like this
RegisterViewController* controller = [[RegisterViewController alloc] initWithNibName:#"RegisterViewController" bundle:nil];
RegisterViewController *news=[[RegisterViewController alloc] initWithNibName:#"RegisterViewController" bundle:nil];
[self.navigationController pushViewController:news animated:YES];
[news release];
If you are using storyboards then you need to get your view controller from the storyboard like
RegisterViewController *viewController = (RegisterViewController*)[[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"vc-identifier"];
Replace vc-identifier with whatever you have given as the identifier in storyboards and replace MainStoryboard with the name of your storybaord.
then pass it into your navigation controller like you are already doing, that is as long as your navigation controller isn't nil
[self.navigationController pushViewController:controller animated:YES];
Just been told that you aren't using storyboards, I was unable to download your link because of my location so I gave a solution with storyboards. My recommendation would be to move to using storyboards.
Will leave this here as it may help others who are having the same problem but are using storyboards
Related
This really should work. This is one of the simplest things to achieve in iOS and for some reason it's just not working.
I have two view controllers in my storyboard. One is InitViewController and the other is ViewController, with a storyboard ID of Init and ViewOne respectively. I have a button on InitViewController that is running code to switch the views. The code is running properly but nothing happens despite that fact. Here is the code:
-(IBAction)NextPage:(id)sender{
ViewController *wc = [[ViewController alloc]
initWithNibName:#"ViewOne"
bundle:nil];
[self.navigationController pushViewController:wc animated:YES];
}
I imported ViewController.h, I just don't know why this isn't working.
initWithNibName: is for view controllers that you create in .xib files, not storyboards. To create a view controller from a storyboard use -[UIStoryboard instantiateViewControllerWithIdentifier:]
ViewController *wc = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewOne"];
[self.navigationController pushViewController:wc animated:YES];
You need a NavigationController - try to log self.navigationcontroller and you will see is null
In your storyboard add a UINavigationController set it as entrypoint, set InitViewController as root view controller and then you can use:
ViewController *wc = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewOne"];
[self.navigationController pushViewController:wc animated:YES];
I have another ViewController inside the same story board to which I want to switch by clicking a button. The problem is when I try to control-Drag the second view controller to create an Outlet inside the ViewController.m file of the primary viewcontroller, an outlet isn't created.
In Android we can open a new Activity with different UI from inside of another activity. I am sure same can be achieved in iOS as well, so my question is how can I create an outlet of the second view Controller and open it programmatically?
It is not possible in iOS to create an IBOutlet from one ViewController to another ViewController, But you can use a UIStoryboardSegue for the purpose.
I will suggest you to follow Tutorial: Storyboards from Apple Documentation. It will help you understand how ViewControllers are actually connected.
Opening SecondViewController programmatically is possible by using Storyboard Identifier, You need to provide storyboard identifier name for the class you want to switch to, see this image , in my demo i have used secondViewController
Now use this code inside your buttonClick event method.
- (IBAction)buttonClicked:(id)sender {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
SecondViewController *secondViewController = (SecondViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"secondViewController"];
// Use this to show your UIViewController in modal transition.
[self presentViewController:secondViewController animated:YES completion:nil];
// Use this to show your UIViewController in push transition with navigation controller
//[self.navigationController pushViewController:secondViewController animated:YES];
}
Try this
Viewcontroller*homeVC;
[self.navigationController setNavigationBarHidden:YES];
UIStoryboard *storyBoard;
storyBoard=[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
homeVC=(HomeVC*)[storyBoard instantiateViewControllerWithIdentifier:#"HomeVC"];
[self.navigationController pushViewController:homeVC animated:YES];
As others mentioned, you cannot do this.
To override and launch VC and keep it's properties you can:
First, create segue between viewControllers: Zoom out the view by double clicking the background of interface builder. Ctrl+drag from one VC to another and choose type of segue (e.g. show).
Than create action for button, in which you can:
[self performSegueWithIdentifier:#"myIdentifier" sender:self];
After that, in -(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender check identifier of segue, set new yourCustomClassViewController and voila!
if ([segue.identifier isEqualToString:#"myIdentifier"]) {
myCustomClassViewController *myCustomVC = [segue destinationViewController];
myCustomVC.oldProfile = newProfile;
}
What I did:
I am using scrollview to view some UIView(s), with paging enabled.
In last page in subview of scrollView I added a button.
I also wrote a function which is in subclass of UIView ,which is invoked when we press that button.
I want to view storyboard when I press that button.
You need to implement protocol method for custom UIView class.
For example;
#import <UIKit/UIKit.h>
#protocol YourCustomViewDelegate <NSObject>
- (void)buttonTapped;
#end
#interface YourCustomView : UIView
#property (nonatomic, strong) id< YourCustomViewDelegate > delegate;
#end
And the .m file you can call buttonTapped delegate method.
- (void)myCustomClassButtonTapped:(id)sender
{
[self.delegate buttonTapped];
}
For proper work;
set your custom view delegate to self in your custom view controller.
add buttonTapped method to that view controller
And do what you want in that method. Present/Push view controllers like the other answers explained.
Edit
I will try to illustrate very simple usage of protocols, hope it will help you.
#import "MyViewController.h"
#import "YourCustomView.h"
#interface MyViewController ()<YourCustomViewDelegate> // this part is important
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
YourCustomView *customView = // initialize your custom view, I suppose that you already did it
customView.delegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)buttonTapped
{
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
}
Take a look at this
YourViewController *obj=[[YourViewController alloc]init];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:obj];
[[[UIApplication sharedApplication]keyWindow].rootViewController presentViewController:nav animated:YES completion:NULL];
try like this
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController* initialView = [storyboard instantiateInitialViewController];
Firstly you need to set a storyboard Id to your ViewController, namely "mainVC". Then you could pus/present it using below code :-
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
//OR presenting VC
[self presentViewController:viewCon animated:YES completion:nil];
Also in case if you want your another storyboard to be initiated then below,
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil]; //Change MainStoryboard with your storyboard id
hope this will help
the way i perceive your question is
->Rightnow your inside you are in UIView class and inside it there is a button by clicking it you want to push or present a ViewController and offcourse from inside your UIView class you cant push or present your view Controller. So
you can do one simple thing first inside action method make a ref(forward declaration) or you can make a whole new object of your ViewController class in which your UIView is present right now , then call a function(which exist in your ViewController) like
//function inside your uiview calss
- (void)btnaction
{
[_objCSInformationViewController pushViewController];
}
// function inside your view controller
-(void)pushViewController
{
yourViewController *objViewController = [[yourViewController alloc]initWithNibName:#"yourViewController" bundle:nil];
[strong.navigationController pushViewController:objViewController animated:YES];
}
My storyboard looks like the following:
What I'm trying to achieve is when "Click Me" is pressed on the home page, to segue to "One" , check some logic on this controller, if successful, automatically segue to "Two".
Then when the "Back" button is pressed on "Two" it would take the user back home, essentially popping "One" off the stack.
Below is what my "One" controller looks like:
#implementation OneViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// example logic, in this case just force them to view two
if(1 == 1)
{
[self.navigationController popViewControllerAnimated:NO];
TwoViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"two"];
[self.navigationController pushViewController:vc animated:YES];
}
}
#end
I'm getting strange behavior and receiving the following error:
Finishing up a navigation transition in an unexpected state.
Navigation Bar subview tree might get corrupted.
I can't seem to figure out what I'm doing wrong. I've included the full dead simple source: http://andrewherrick.com/spike/pushpop.zip
EDIT:
I've tried moving the logic to ViewDidAppear and it simply kicks me back to the "Home" view automatically which isn't what I want.
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewDidAppear:(BOOL)animated {
// example logic, in this case just force them to view two
if(1 == 1)
{
[self.navigationController popViewControllerAnimated:NO];
TwoViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"two"];
[self.navigationController pushViewController:vc animated:NO];
}
}
Putting your second push logic in viewDidAppear: rather than viewDidLoad solved the problem for me.
You should also consider the UX of your app. If a viewController is being used only for a few seconds to process some data and automatically segues into another viewController, it would be better practice to show a UIActivityIndicator or a small visual indicator.
EDIT:
Your automatic push should not pop itself before pushing another.
- (void)viewDidAppear:(BOOL)animated
{
if(1 == 1)
{
TwoViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"two"];
[self.navigationController pushViewController:vc animated:YES];
}
}
Then in your TwoViewController you need to programmatically call
[self.navigationController popToRootViewControllerAnimated:YES];
in order to pop back to your Main viewController.
I was having memory management issues, finally found out the problem, I keep instantiating new view controllers. When the app launches it goes straight to the FirstViewController which is an element inside of UITabBarController in the storyboard.
I then show FilterViewController with this method:
- (IBAction)searchOptions:(id)sender {
FilterViewController *ctrl = [[FilterViewController alloc] init];
[UIView transitionFromView:self.view toView:ctrl.view duration:1
options:UIViewAnimationOptionTransitionCurlUp completion:nil];
self.filterViewController = ctrl;
[self.navigationController pushViewController:self.filterViewController
animated:NO];
}
Which works fine and brings up FilterViewController which has its own .xib, so it is not in the storyboard.
Now when trying to pop back to FirstViewController I use this method:
- (IBAction)backToMap:(id)sender {
// i used the below when trying to push another view controller
/*UIStoryboard *storyboard = [UIStoryboard storyboardWithName
:#"MainStoryboard" bundle:nil];
FirstViewController *fvc = [storyboard
instantiateViewControllerWithIdentifier:#"FirstViewController"];
fvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;*/
[self.navigationController popViewControllerAnimated:YES];
}
However it doesnt do anything. Nothing at all, I cant see what is wrong here?
popViewontrollerAnimated is only used when you have pushed your view controller onto a navigation stack, so it won't do anything here unless there is one in your project.
When you use transitionFromView... you are replacing your current view with the new view so you will need to call it again to get back to your old one.