I'm know how to use storybaord drag line to exit use unwind method.
I have four uiviewcontroller (A~D).
I write the code in B UIViewcontroller
-(IBAction) backToMenu:(UIStoryboardSegue *) segue
{
}
I know It's can drag the action to the green button(exit) to set the back action in the D UIViewcontroller.
It will show the backToMenu method name and they can link.
Now, I want to use programming to implement the drag to green button (exit) action.
But I don't know how to write this part.
I don't use popViewControllerAnimated method. because I need from D UIViewcontroller back to the B UIviewcontroller.
And D UIviewcontroller have a condition if a variable is YES, will unwind to the B(backToMenu) method.
Have any one know how to use the code implement the "drag line to the exit button" action?
(I am use navigation push, not modal)
Thank you very much.
You should've read the docs.
[self.navigationController popToViewController:vcB animated:YES];
Related
I am trying to write an app using UINavigationViewController. My first screen has several buttons on it, and on the click of each button, I want to segue to a UIViewController. I know that I can add a segue on each button, all pointed to the UIViewController that I want to go to, but I was wondering if it is possible to use only one segue that can be fired from each of the buttons.
If that is not possible, I was wondering if it was possible to open the second UIViewController from the first one, on button click, and provide a Back button like the UINavigationView provides. I did manage to get everything on this idea working, except for the back button. I mean I can put a standard button somewhere on the screen and go back, but I'd like the standard back button on the UINavigationView.
Phew! I'm not sure if that makes any sense.
I know that I could also use a tableview, but I'm trying to set this up with buttons.
Thanks
Edit: Thank you to everyone that answered. I now have this working. I would vote up the answers, but I don't have enough posts to do it. I appreciate the answers!
If you need to have separate action functions for each button, suggest that you segue from the main controller to the other controller and create a segue identifier (see xcode procedure below); then, use performSegueWithIdentifier from each of the button action functions. You can also take advantage of the prepareForSegue. To create the segue, control-drag from the left button in the controller in the storyboard to the controller you want to segue to and pick show.
Check the example code in swift that I did for a very similar problem in the SO reference
Linking View Controllers through button
You can embed the main controller in a navigation controller and that will give you the ability to navigate back. If you have multiple layers you can also use unwind segue.
Link each button to one single action (ex. buttonClick) in that ViewController and then perform the appropriate segue using pushViewController method on self.navigationController
-(IBAction)buttonClick:(id)sender {
if(sender.id == self.button1) {
DestinationViewController *vc = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"VC_IDENTIFIER"];
[self.navigationController pushViewController:vc animated:YES];
}
Or if you already have that 1 segue defined in storyboards you can use
[self performSegueWithIdentifier:#"SegueIdentifier" sender:self];
And use that inside the buttonClick method. Using the 1st example, or the second one as long as the segue you setup in the storyboards is a push then you should already get the back button as that is the default behavior for pushing view controllers onto the navigation stack.
In storyboard we have great feature that allow us to make Show (e.g. push). So seems the logic is next:
If we don't have navigation controller then view controller will use present modal logic. My question is there any inverse action that I can use with Show?
I have a UIButton that close current view controller screen:
- (IBAction)onTappedCloseButton:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
But in case if I don't have navigation controller, how can I simple use inverse action to go back? So my solution is to check if self.navigationController is nil then use dismissing option:
[self dismissViewControllerAnimated:YES completion:nil];
But maybe there is another cool solution like Show (e.g push). But Close (e.g. pop)?
Yes, you can use an unwind segue to go back, and it will be the reverse of whatever the forward segue was.
You have two options on how to do this:
1) The Unwind segue
To make an unwind segue you have to add a method in the view controller you want to "unwind" to with the following format:
-(IBAction)someSelectorName:(UIStoryboardSegue *)sender;
You will then be able to drag from your UIButton up to the "exit" icon in your storyboard.
Wire it up to the selector you just defined and UIKit will figure out how to get back to that view controller without you having to write any code. This can be especially useful as it can figure out when it needs to call -dismissViewControllerAnimated: more than once and can call those methods successfully. It can even unwind from within a view controller embedded in a navigation controller when the view controller you're unwinding to has the navigation controller presented on top of it. (i.e. it will do a dismissViewController instead of a pop to unwind)
2) The Custom unwind method
Say you don't want to or cant trigger this action from a storyboard. There is still an option and its detailed over at this question here:
Whats the programmatic opposite of showViewController:sender:
The gist is you can write your own generic dismiss method by implementing categories on the UIKit container View controllers (or on your own container)
Here is my storyboard configuration:
Navigation Controller -> View Controller A -> Push-> View Controller B
^
|
Modal
^
|
View Controller C
What I want to achieve: When a button is pressed in View C, directly View B will be opened modally (No part of View A is to be displayed). Also, View B will have a navigation back button to View A.
To achieve this,
I set up the illustrated storyboard.
I created a segue between View C and the Navigation Controller of View A/B.
In the 'prepareForSegue' method of View Controller C, I get an instance of View Controller A as the first element in the navigation. In this instance, I set a variable like 'directlyProceedToViewB=YES'.
In the viewDidLoad method of View Controller A, I check the variable 'directlyProceedToViewB' and if it is YES, I call 'performSegueWithIdentifier' to segue to View B
The result is so that, first View A is opened modally and after displaying it a very short time, View B is opened with a push animation (View B can navigate back to View A, which is good). But I do not want View A to be displayed any time at all. How can I achieve this?
EDIT:
To better visualize, I'm adding a screenshot with more example cases to support:
Here are some cases I want to support:
We can start with ViewC, click on 'Modally Display B' which opens ViewB, then click 'Back to A' to navigate back to ViewA, then click on 'Dismiss Modal' on ViewA to go back to ViewC
We can start with ViewD, clcik on 'Modally Display A' which opens ViewA, then click on 'PushB' to open ViewB, then go back and forth between A and B and modally dismiss to ViewD.
First of all, some corrections: those are not views but view controllers. And "view A" is not pushed into the UINavigationController but it's the root.
After that, I suggest making the segue in "view C" an unwind segue and implement the IBAction in "view A" by pushing "view B" with [[self navigationController] pushViewController:bViewController animated:NO].
EDIT (adding some details):
I assume that in ViewControllerA's viewWillAppear you present ViewControllerC in a not animated manner.
Implement an unwinding action like (IBAction)unwindAndThenGoToB:(UIStoryboardSegue *)segue in ViewControllerA.
In the storyboard connect the button in ViewControllerC to the Exit icon and select the previously defined method.
Then implement the method with the push call I wrote earlier.
ps: for documentation there is plenty on Apple's website.
Implement this using delegates.Decalre protocol in which class you want and define those methods and call the methods in the view controller you want.There is no many ways of calling some view and showing back button to go different view.modal view is just a concept.and you can use delegate methods to call whatever class you want.
Here I got a way to do so:-
You need to set no animation for segue from viewC to viewA as shown in below image. Then set a segue identifier for segue from viewA to viewB namely, "viewB" and in your viewA .m file add following code,
- (void)viewDidLoad {
[super viewDidLoad];
// Place your conditional check here.
[self performSegueWithIdentifier:#"viewB" sender:self]; //Will directly lead to viewB and viewA won't be shown as no animation is there from viewC to viewA.
}
And your rest flow be like-wise.
I found the solution myself.
First, I discovered that, my original proposal of
In the viewDidLoad method of View Controller A, I check the variable
'directlyProceedToViewB' and if it is YES, I call
'performSegueWithIdentifier' to segue to View B
works as I desired on iOS 7 but does not work on iOS 8.
So the solution is, in the viewDidLoad method of View Controller A, if 'directlyProceedToViewB' is YES, rather than calling performSegueWithIdentifier, use the following code:
ViewControllerB *destVC = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewControllerBStoryboardID"];
[self.navigationController pushViewController:destVC animated:NO];
I am not a regular user of interface builder but I have to use it for this project.
I am using storyboards and have managed to create a push segue from one view controller to another. Lets call it from A to B. Now I am trying to unwind that segue and return from B to A.
I do not need any information to be passed between controllers. I just need to go back.
I have a UIBarButtonItem navigation bar of B, and I have followed this tutorial.
I did this:
A) Created this method on B
- (IBAction)backToViewControllerOne:(UIStoryboardSegue *)segue {
NSLog(#"from segue id: %#", segue.identifier);
}
B) The tutorial author says: "Link this method to a button in the view that you want to unwind from." but this cannot be done because the method has this parameter :(UIStoryboardSegue *)segue and Xcode will not allow a button to be linked to this method, because it expects the method to have this parameter :(id)sender. If I change the parameter to that, the triggered segue cannot be linked.
C) link the button to the green exit on storyboard, choosing the method on 1. OK, did that.
Did all this and clicking on the button does nothing. Not even the action is triggered.
How do I solve that puzzle?
A method with with a particular signature, an IBAction with an argument of type UIStoryboardSegue, needs to be in the controller that you are unwinding to. That (and any other methods like it that you might have in other controllers) will show up in the exit button (of the controller you're unwinding from) when you control-drag to it.
I'm finding some difficulties here. I'm setting up an UITableView where users can add stuff to. I'm done with the AddViewController, where users can get to by pressing the + on the UIBarNavigationButton, and then Push Segue to my AddViewController.
Here in my AddViewController is an Array where the user's data is stored in. Now how do I get the data in my UITableView in my FirstViewController array? I was thinking with another Push Segue from the Save UIBarNavigationButton and pushing the User array into the TableView Data?
Is this the right way to do it?
Kind Regards
Following along with what Tander said, you should use an unwind segue not push. Follow this example as a general guideline.
Use a similar setup like this in your FirstViewController:
//FirstViewController.m
- (IBAction)setArrayFromPreviousController:(UIStoryboardSegue *)segue
{
AddViewController *controller = [segue sourceViewController];
//old array and new array are the two array variable names
[self setOld_array:[controller new_array]];
}
Alternatively, you could use a protocol method along with a delegate. This is a little bit more complex:
A great tutorial on how to accomplish this can be found here.
If you're asking if you should use a push segue to move data back to previous controller, the answer is no.
What you can do is use unwind segues for this:
https://developer.apple.com/library/ios/technotes/tn2298/_index.html
For transforming data from B ViewController to A ViewController, you can use Unwind Segue, Protocols and Delegate and also Blocks.
Here i am showing you how to transform data using Protocol & Delegate.
In B VC, in H file add
1) Just above #interface:
#protocol addDataProtocol <NSObject>
-(void)addData:(NSArray *)arrayData;
#end
2) dd property
#property(nonatomic,retain)id<addDataProtocol>delegate;
3) In the M file, just before [self.navigationController popViewControllerAnimated:YES]; add:
[self.delegate addData:yourArray];
4) In A VC:
confirm the delegate before pushing, like : objBViewController.delegate=self;
5) Call the method:
-(void)addData:(NSArray *)arrayFromB
and access arrayFromB.
On your TVC you have to create an action which accepts a UIStoryboardSegue (I think). On you AddVC you can ctrl-drag the exit button to the little green icon on the storyboard scene. You then conect one with another. All you have left to do is to implement prepareForSegue on AddVC so you can pass your array back to the TVC. BTW, the action on TVC should also accept the array you're passing.
You can do a search on youtube, there must be a bazilion of tutorials about it.