I am trying to change where a button leads to depending on the selected row of a picker view. I am trying to display data depending on a certain year and I can make the picker display the available years and change a label to the corresponding year, but how can i make the "go" button I;ve created lead to the correct view controller?
Maybe you haven't had time to figure this out, maybe you have, but this is what I would do. You have a text field that you will populate with a picker, call this the "yearTextField." Then you have a button that you want to change the action depending on the year in question. Call this "myChangableButton." This is just for an example, you can call them anything you like. I put my initial view controller in a navigation view controller to have better control of the views. For this example I made two different years 1942, and 1971. They each have their own view controller that I named "FourtyTwoViewController" and "SeventyOneViewController" in my first view controller you will need to import these into the .m file. Like this..
#import "ViewController.h"
#import "FourtyTwoViewController.h"
#import "SeventyOneViewController.h"
Also, make sure when you drag out the new view controllers in the storyboard, that you name them as such. And don't forget to use that name as the Storyboard ID, found under the Identity inspector. Now for myChangableButton I made an action that will bring up whichever view controller you want based on the text in the yearTextField like this..
- (IBAction)myChangableButton:(id)sender
{
if ([_yearTextField.text isEqual: #"1942"])
{
FourtyTwoViewController *ftvc = [self.storyboard instantiateViewControllerWithIdentifier:#"FourtyTwoViewController"];
//[self presentViewController:ftvc animated:YES completion:nil];
[self.navigationController pushViewController:ftvc animated:YES];
}
else if ([_yearTextField.text isEqual: #"1971"])
{
SeventyOneViewController *sovc = [self.storyboard instantiateViewControllerWithIdentifier:#"SeventyOneViewController"];
//[self presentViewController:sovc animated:YES completion:nil];
[self.navigationController pushViewController:sovc animated:YES];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Watch Out!" message:#"Put in valid date" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
}
The line of code that I commented out will bring up a modal transition, but I prefer a push since that gives you a great back button. That's it. I hope this helps you on your project. Make a comment if you have any questions, and good luck. And WELCOME! to SO!!
EDIT #1
Here is a sample of how I set the initialUrl in a viewcontroller that I pushed.
VideoViewController *vvc = [self.storyboard instantiateViewControllerWithIdentifier:#"VideoViewController"];
vvc.initialUrlString = urlString;
vvc.descriptionString = descriptionString1;
[self.navigationController pushViewController:vvc animated:YES];
I imported VideoViewController into the first view controller. And VideoViewController has two properties called initialUrlString and descriptionString. In the first view controller I have two properties called urlString and descriptionString1, these are set in the first view controller during another method and then passed into the second.
Related
So I was create three UITableViewControllers with UINavigationController. I want a back button on 3rd UITableViewController, what returns my view to first UITableViewController instead of second.
How can I do that? That must be a real backButton, not a image or something else. Will be perfect to do this only with storyboard.
UPDATE
Perhaps I poorly explained what I want.
I don't want use any button with action on it. I just want something like as setting "address" of 1st TableViewController on my default back button. There is any way to do it?
add a button and connect it to following action
- (IBAction)backToFirstView:(UIButton *)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
(or)
[self.navigationController popToViewController:yourFirstViewControllerObject animated:YES];
}
There are different ways to navigate from DetailViewController to other view controllers.
We will go through the cases one by one.
First of all I would like to clear that if its your default
navigation bar's back button, then it must return to the last most
view controller only which is actually a default behavior of a
navigation controller.
Second, If you would like to go back to the
last most view controller on the tap of a button placed by you, you
should write the following code
[self.navigationController popToViewController:NAME_OF_A_VIEWCONTROLLER animated:YES];
Third, If you would like to go to the first view controller from where you
started, you should write the following code
[self.navigationController popToRootViewControllerAnimated:YES];
Ok, I found a way to resolve my problem. Thanks for your answers guys, they was very helpful.
So for resolve this problem you just need use link what give me Kumar KL upper, and wrote next method in your UITableVIewController
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
// Navigation button was pressed. Do some stuff
[self.navigationController popViewControllerAnimated:NO];
}
[super viewWillDisappear:animated];
}
Now you got a backButton what redirect you to your viewController, BUT title of this button is wrong. Let's resolve that unfair.
Create new class CustomSegueцрфе inherited from UIStoryboardSegue with next code in CustomSegue.m :
- (void)perform
{
UIViewController *sourceView = (UIViewController *) self.sourceViewController;
UIViewController *destinationView = (UIViewController *) self.destinationViewController;
[[destinationView navigationItem] setTitle:#"TitleOfYourViewController" ] ;
[sourceView.navigationItem setTitle:#"TitleOfButton"] ;
[sourceView.navigationController pushViewController:destinationView animated:YES];
}
Now you can go to storyboard and connect 2nd ViewController with 3rd with custom segue.
Like you see UINavigationController uses Title of previous ViewController for button title, so you just need change it.
I have a modal view controller that I called in from another view controller. Upon dismissal of the modal view controller, I want a method to be called on the view controller that presented that modal view. What is the easiest way to do this?
I tried doing this in my modal view controller: [(ParentViewController*)self.presentingViewController foo]; before calling [self dismissViewControllerAnimated:YES completion:nil];.
Xcode gives me an error saying foo isn't recognized, even though it is defined and prototyped in the controller. If your solution involves blocks, I really don't understand them so I would appreciate it if you would add more detail. Thanks.
ParentViewController.h
#interface ParentViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>
{
NewAssignmentViewController *newAssignmentViewController;
TableViewDataSource *data;
}
-(void)foo;
#end
You need to get a correct reference to your presenting controller like this:
ParentViewController *presenter = [(UITabBarController *)self.presentingViewController viewControllers][0]; // 0 is assuming that ParentViewController is in the first tab. Change if necessary
[presenter foo];
The other way to do it would be to use delegation, but that's an answer for another time.
If you are using a Storyboard segue to present your view controller you could dismiss it using an Unwind Segue. An unwind segue is a special kind of segue that unwinds the presented view controllers back to a presenter.
To accomplish this, you would create a method in the presenting view controller with the following signature:
- (IBAction)unwindAction:(UIStoryboardSegue*)unwindSegue;
This is different than a standard IBAction because the parameter type is a UIStoryboardSegue* instead of the normal id type (it doesn't have to be named unwindSegue:, it could be modalViewFinished: or whatever you like - the important part is that it has a return type of IBAction and a parameter type of UIStoryboardSegue*).
Once you have this method defined, in your storyboard you control-drag from the modal view controller icon (below its view, in the little bar of icons) and release the connection on the green exit sign. This will create an unwind segue, which you should give an identifier in the attributes inspector. Unwind segues will not show up visually in the storyboard canvas, so you will have to find it in the list of items on the left side of the canvas (this is collapsed by default, expand it by clicking the little circular button in the lower left hand corner of the canvas).
Once you've done that, rather than calling [self dismissViewControllerAnimated:YES completion:nil], just call [self performSegue:<Identifier you gave the unwind segue>] instead. During this process the unwindAction: method defined on the presenting view controller and the prepareForSegue: method on the modal view controller should be invoked. You can do whatever cleanup you need to do in these methods (calling the foo method from unwindSegue:, for example).
You call the method on the UIViewController that is your MainView, and pass it your UIViewController you want to be the ActionSheet.
UIActionSheet *actionSheetController =[[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"show otherview", nil];
[self presentModalViewController:actionSheetController animated:YES ];
To dismiss the UIActionSheet, dimissWithClickedButtonIndex:animated: is a method for the UIActionSheet that you can implement. The method can be called by whoever (so if you want to dismiss it from your mainview have a reference to the action sheet and do something like
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
{
switch (buttonIndex){
case 0:
{
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
break;
case 1:
{
MyClass *myclassObject = [[MyClass alloc]init];
[myclassObject foo];
}
}
}
The method is also called whenever the 'cancel' button is clicked by the user.
Use this ModalViewControllers link for better understanding...!
I have tried a few answers on this site, but none of them seem to relate to my problem
I have a MasterDetail app which has a two types of segues that I am using. When you press a button on the detail view, it uses a push segue and pushes another detail view onto that. In the new detailview (the one that was just pushed on) there is a button which calls up another UIView (form sheet) using a modal segue.
What I am trying to do is when the user selects a row, a UIAlertView will show up displaying a message, while at the same time (doesn't have to be at the same time) it dismisses the UIViewcontroller (modal) and goes back from the Viewcontroller that was pushed on. Basically, I need to be able to dismiss all viewcontrollers, one modal and one push (nav) so that the view returns to the original main screen that they started with.
I have the UIAlertView working fine and I can get the modal viewcontroller to dismiss by using [self.dismissViewControllerAnimated:YES completion:nil]; but I don't know how to dismiss the next Viewcontroller (which is in a navigation controller). Using this: [self.navigationController popToRootViewControllerAnimated:NO]; does not work.
Here is where I want to call the function to remove all views:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlWithIDAndChallenge];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
UIAlertView *message = [[UIAlertView alloc] initWithTitle#"Started" message:#"The challenge has begun!" delegate:nil cancelButtonTitle:#"OK!" otherButtonTitles:nil];
[message show]
//right here is where I would normally dismiss the modal VC
//here is where I would like to dismiss all VC
}
If you want, in iOS 6.0 (and later) projects you can use an unwind segue. For example, you can:
In your top level view controller (the one you want to unwind to, not the controller you're going to unwind from), write an unwind segue method, in this case called unwindToTopLevel (personally, I find it useful if the segue bears some indication as to what the destination of the segue is, for reasons that will become apparent when we get to step 3, below):
- (IBAction)unwindToTopLevel:(UIStoryboardSegue *)segue
{
NSLog(#"%s", __FUNCTION__);
}
In the Interface Builder scene from which you will initiate the unwind, control ⌘-drag from the view controller icon to the exit icon to create the unwind segue:
Generally you'd define the segue from a button to the exit outlet (and you're done), but if you want to invoke the segue programmatically, you might want to create it between the controller and the unwind outlet, like shown above.
You'll get a little pop up that includes the name of your unwind segues (from the presenting controllers ... it's like magic):
If you're going to invoke that segue programmatically, you have to select that unwind segue in the document outline on the left side of the IB window and once you've done that, you can give the unwind segue a storyboard id:
I generally use the name of the the unwind segue for the storyboard id, but you can use whatever you want.
Now, having done that, your alert view can invoke the segue:
- (IBAction)didTouchUpInsideButton:(id)sender
{
[[[UIAlertView alloc] initWithTitle:nil message:#"go home" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil] show];
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex])
{
[self performSegueWithIdentifier:#"unwindToTopLevel" sender:self];
}
}
From the class you presented your modal view
call dismiss of modal and then perform selector after some delay and then do the
here is the sample code
//Write this in the class from where you presented a modal View.
//Call the function from modal class when you want to dismiss and go to root.
- (void) dismissAndGoToRoot {
[self dismissViewControllerAnimated:YES completion:nil];
[self performSelector:#selector(gotoRoot) withObject:nil afterDelay:0.50];
}
- (void)gotoRoot {
[self.navigationController popToRootViewControllerAnimated:NO];
}
Here you will call the function
//right here is where I would normally dismiss the modal VC
//here is where I would like to dismiss all VC
[self.parentViewController dismissAndGoToRoot];
If this does not work then take an instance variable of ParentViewController in modal class and assign when presenting modal view controller.
You could try replacing [self.dismissViewControllerAnimated:YES completion:nil]; with
self dismissViewControllerAnimated:YES completion:^{
[parentViewController.navigationController popToRootViewControllerAnimated:YES];
}
I believe parentViewController will point to the presenting view controller, and the block will cause the parent view controller's navigation controller to pop to the root view controller.
I'm having a lot of trouble with this, and I can't seem to find an answer specifically to this situation.
I have a UITableViewController that has a button, that upon being clicked presents a UIActionSheet with a few options. I want one of the options to bring up another view controller that I have already present in my storyboard, ready to be shown.
The UIActionSheet is fully implemented, with the actionSheet:clickedButtonAtIndex: as well, I just don't know what to do within it.
I tried having this within it:
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Text"]) {
AddTextViewController *addTextViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"addTextViewController"];
[self presentViewController:addTextViewController animated:YES];
}
But I get an error saying: No visible #interface for 'RootViewController' declares the selector 'presentViewController:animated: so that's not working either.
What exactly am I supposed to be doing here?
There is no such method as presentViewController:animated:. The method is actually presentViewController:animated:completion:.
So change:
[self presentViewController:addTextViewController animated:YES];
to:
[self presentViewController:addTextViewController animated:YES completion:nil];
Pass in an actual completion block if desired.
Currently using Xcode 4.2 and I have two view controllers (1 and 2). I have a number of textfields in viewcontroller1 that need to be filled in before the user is able to click the "Next" button which then goes to viewcontroller2. I have got alertdialogs that popup if the user hasn't filled in all the textfields.
I have used the storyboard to segue the button click which works fine, except if the textfields are empty, my alertdialog pops up but the view controller still changes to number 2.
How do i make it so that only if my if/else statements are met, does the next button go to the next view controller.
I am using a navigation controller to control the view controllers.
I tried to put the following code into the if/else statement but it didn't work:
UIViewController *secondViewController = [[SecondViewControllerClass alloc] initWithNibName:#"<name of xib>" bundle:nil];
[self presentModalViewController:secondViewController animated:YES];
Now there was a few things I was unsure about when trying to find out how to use this method. Do i need to import the SecondViewController.m at the top of the firstviewcontroller.m?
NSString has a helpful property called length, which will return nil if a textfield contains no text. If you need to check, call:
if (!myTextField.text.length) {
//no text in the box
}
Simple enough, since you have already set up the alert boxes to pop up if something is wrong with the textbox input, make sure the alert box show/init code is before the code that changes the view and do this:
if(//something is wrong with the textbox input)
{
UIAlertView* alert = [[UIAlertView alloc] initWith...
[alert show];
//Add a return! If the method is not IBAction or void, just return nil
return;
}
Voila!