I have defined a segue from source tableview controller to another and trying to programmatically transition to the destination controller upon click of a UITableViewCell using the following statement:
[self performSegueWithIdentifier:#"pushToDestinationViewController" sender:self];
However, I find that the segue doesn't result in a "push" to the destination view controller.
On the other hand, if I wire the segue to a specific cell in the source view controller it works.
In addition, if I call the destination viewcontroller programmatically using:
[self showViewController:DestinationViewController] it works.
Can someone advise if this is a known issue in iOS 8 or if I am missing something here.
Did you have a segue in your Storyboard called pushToDestinationViewController? You will need to make sure that you have this segue in your Storyboard first like below.
Or, if you just want to simply push another view controller, you can just use [self.navigationController pushViewController:destinationViewController].
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.
so I inherited an old project at work that's broken up into a ton of different storyboards. While this hasn't really been too much of a hassle, the client now wants a custom segue animation that goes from a View Controller on Storyboard A to a View Controller on Storyboard B and I can't figure it out for the life of me.
I have the animation worked out if the views are on the same Storyboard, but I can't get it hooked up to a transition to another storyboard.
You can't do this without using a trick, because you can't connect a segue between storyboards. You can instantiate the controller manually in the other storyboard, then do whatever custom animation you want to present or push it in code. Since the main reason for using a segue (as opposed to transitioning to the new controller in code) is that you can see the connections between your controllers in the storyboard, there's not much reason to use a segue in your case.
If you really insist on using a segue, then you need to put a "dummy" controller in your first storyboard that you connect a custom segue to. The code in that segue switches out the dummy controller for the real controller you want to segue to in the other storyboard. You can find a reference to that technique here, http://spin.atomicobject.com/2014/03/06/multiple-ios-storyboards/.
Find below code for accessing another storyboard view:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"storyboard_A_view_identifier"]) {
UIStoryboard *storyBoardB = [UIStoryboard storyboardWithName:#"storyBoardB" bundle:nil];
UIViewController *anotherViewController = [storyBoardB instantiateViewControllerWithIdentifier:#"storyboard_B_view_identifier"];
// use anotherViewController and perform custom animation on it
}
}
I have a storyboard segue with an identifier that is 'Push to ResumeView'.
I try calling it in the ViewController that I'm in at the point, by doing
[self performSegueWithIdentifier: #"Push to ResumeView" sender: self];.
But nothing happens?
I'd much rather just push the ViewController using the top NavigationController or something, but I can't see how to do that either.
Try implementing the shouldPerformSegueWithIdentifier:sender: or prepareForSegue:sender: methods in the 'from' view controller. Put a break point or NSLog() inside the method to inspect the segue identifier. This will prove that you indeed set up the segue correctly in the storyboard.
If you want to manually push your next view controller to the top of the navigation controller, use pushViewController:animated:. However, if you are using storyboard, the preferred way is to use segues.
Try this one.
UIViewController *yourResumeView=[self.storyboard instantiateViewControllerWithIdentifier:#"PushToResumeView"];
[self.navigationController pushViewController:yourResumeView animated:YES];
I use three view controllers and on each view controller I put UITableView and UITableViewCell. When I connected from the first view controller's table view cell to another view controller's from within storyboard and ran the simulator, the segue works as expected. However, when I connect from the second view controller's table view cell to the last view controller from within storyboard IN THE EXACTLY SAME WAY as the first one, then for some reasons the transition doesn't work.
If I define didSelectRowAtIndexPath: and within it call [self performSegueWithIdentifier:#"showDetail" sender:self]; in the second view controller's implementation file, the transition can work as expected. I don't care about whether it's storyboard segue or methods defined in my code to perform the transition, as long as the transition does work correctly.
However, I'd still like to know why such inconsistency occurs. As I said, I connected two storyboard in the exactly same way in both cases and checked out attribute inspector and connection inspector, but I don't find any differences between the two connection there.
Also, while the first view controller can perform the transition without the method being defined, when I define it then the transition doesn't work, issuing the following error message:
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
I think I cannot use both approaches (i.e. storyboard segue and method calls) - I just wanted to know what derives the inconsistency here.
I use iOS 7 and Xcode 5.
First of all, if you use push segues, you can't make a push for the second segue if the first segue is modal (unless you embed your second VC in a navigation controller).
Second, make sure de segue identifiers are unique for each segue.
If you ctrl+drag a segue in storyboard, don't call performsegue in code, you just attempt to do the same operation twice. If the segue is in storyboard, in code you should use prepareforsegue delegate.
Another way of doing all of this is not using any segue in storyboard, then in code #didselectrowatindexpath you can instantiate your destination vc using [storyboard instantiateviewcontrolerwithidentifier...], then [self.navigationcontroller pushviewcontroller..] for a push segue or [self presentviewcontroller...] for a modal.
EDIT: Also, when you ctrl+drag, make sure you are dragging from the cell and not from the table.
Self Answer
I finally found out that the issue was not caused in storyboard - it's on the implementation code. Since I have to use UITableViewCellStyleValue1, I cannot use dequeueReusableCellWithIdentifier, and for some reasons the dequeueReusableCellWithIdentifier has to be used in order to make an automatic transition from cell to another view controller from within storyboard only. I checked out that using dequeueReusableCellWithIdentifier and disabling UITableViewCellStyleValue1 temporarily makes it successful to make the transition without didSelectRowAtIndexPath: method being defined.
I am creating an app using iOS 5 SDK. I managed to push views using the Storyboard's Segues, but I cannot find the proper way to pop the current view and go back to the previous one.
I am not using any navigationController (the app doesn't have any top or bottom bars).
I don't think using modal or push segue the other way would be the solution as it instantiates a new controller.
Do I have to use a custom Segue with the opposite animation and deletion of the view at the end ? Or is there a better way ?
Storyboards in iOS 5 don't provide a "no-code" way to return from a segue -- that's something you'll need to implement yourself.
If you use "push" segues (which require a navigation controller), use the navigation controller's popViewControllerAnimated: method to undo the last push segue. (Or other methods to undo more; see the UINavigationController documentation.)
If you use "modal" segues, call dismissViewControllerAnimated:completion: on the view controller which presented the current view controller (which you can get from its presentingViewController property).
Update: In iOS 6 and later there's unwind segues for going "back" in a storyboard. It's still not a no-code solution -- and it shouldn't be, because you need to be able to do things like differentiating between "Done" and "Cancel" exits from a modal view controller. But it does let you put more of the semantic flow of your app into the storyboard. Apple has a tech note that describes them in detail, and they're also covered in the video from WWDC 2012 Session 407.
You could try calling [self dismissViewControllerAnimated:YES completion:nil]; from the controller you want to dismiss (whether the controller has been pushed, or shown modally).
Here is the related documentation : UIViewController Class Reference
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.
Just to clarify.
In the class that was pushed. Simply wire up the following and the controller and view will be popped off.
[self.navigationController popViewControllerAnimated:YES];
Create Segue type "Custom" on your stroyboard. This can be from a button.
Create a new UIStoryboardSegue class named "popSegue"
In the popSegue.m file add the following;
-(void)perform{
UIViewController *sourceViewContreoller = [self sourceViewController];
[sourceViewContreoller.navigationController popViewControllerAnimated:YES];
}
-In the storyboard editor.
-Select the segue and change the Segue Class to "popSegue"
-Set the Identifier to "popSegue"
Done!
You can use the same "popSegue" class throughout your project.
Hope this helps
I'm using Xcode 5 also and here's how it's done. First, in the view code file that pushed the other, create an IBAction method in the .h file such as this:
- (IBAction)exitToHere:(UIStoryboardPopoverSegue *)segue sender:(id)sender;
Then in the .m file add this:
- (IBAction)exitToHere:(UIStoryboardPopoverSegue *)segue sender:(id)sender {
}
You can add any cleanup code you want executed in this method. Next go to your storyboard and select the pushed view. I assume you've got some kind of button on the view that the user taps to signal he's finished. Click on that button, hold down the key and drag to the the green box below the view which is the Exit. Release the mouse button but continue to hold the key. A popup will appear and your method will show in the list. Select that method. Now when the user clicks on the button, the view will pop and you'll be returned to the starting method.