So I have this code on a page:
#IBAction func showKaart(sender: AnyObject) {
performSegueWithIdentifier("menuToKaart", sender: sender)
}
And the segue "menuToKaart" does go to the right place but the problem is that it's not using the Navigationcontroller because it's 1 page up. Because of that I am not able to go back.
(sorry if the picture is unclear)
What I am trying to do is this:
Inside ViewController2 is a button called "Kaart" which leads to the viewcontroller "Kaart"
I want a button inside Table View "Locaties" to use the same segue as the button "Kaart" in ViewController2. This works with the code I am using but it doesn't use the navigation controller so there is no navigationbar where I can press back to go back to "ViewController2"
Related
I have a Main Tab Bar Controller with 3 Views.
Main View
History View
Menu View
When my App first loads, the Tab Bar Controller checks if the user is Logged On, if she is not, it segues to a Logon view. Once the user Logs On I call an Unwind Segue from the Logon View as follows:
self.performSegueWithIdentifier("unwindToTabBarFromSignInView", sender: self)
This brings the user to the Unwind Segue of the Menu View in my Tab Bar controller since this is the View with the Logout button, thus it was the View that was presented to the User last. However, I would like to present the Main View instead of the Menu View once the user Logs On. To accomplish this I have the following code in the Unwind Segue. Unfortunately, it seems to have no effect, the user keeps being brought back to the Menu View once they Log On instead of the Main View.
#IBAction func unwindToTabBarFromSignInView(segue: UIStoryboardSegue) {
tabBarController?.selectedIndex = 0
}
It's curious that that doesn't work. But I have an easier solution.
When unwinding to a UITabBarController, every tab's ViewController can implement its own unwind #IBAction and you can do directly to the tab you want.
In your MainViewController implement this:
#IBAction func unwindToMainViewController(_ segue: UIStoryboardSegue) {
print("back in MainViewController")
}
Create the unwind segue by control-dragging from the ViewController icon to the Exit icon and give it an identifier "unwindToMain". Once the user logs on, simply call:
self.performSegueWithIdentifier("unwindToMain", sender: self)
and you will return to the Main tab of your UITabBarController.
I have a simple app I am building. A list of items in 1 view controller with a table view and embedded navigation controller. When you select a row it brings you to the details screen (no problem).
Push from List View to List Item
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "ListItemDetailsVC", sender: nil)
}
Pop back from list item to List View
#IBAction func backToInboxTapped(_ sender: Any) {
navigationController?.popToRootViewController(animated: true)
}
This works fine!
My issue is that I have another view controller (add item) that presents modally when add button is clicked. The idea is that when it saves it brings you to the list detail vc.
#IBAction func saveItem(_ sender: Any) {
performSegue(withIdentifier: "DetailsFromAdd", sender: nil)
}
Opening up the details view controller from the add new controller works fine but once I open the details view I want to be able to go back to the rootViewController. The button does not work anymore
In your case you should not need to use segue. You have to clear some concepts.
You can't popToRootViewController or VC if you have pushed or show view controller from modally presented vc!!
Now if you want to achieve this then you have to make some changes that I am trying to mention below :
take one global variable or property (objective c concept) in your add item VC. now when you come to add item VC from lust VC set this global variable or property to self something like,
AddListItemVC *advc = [self.storyboard instantiateViewControllerWithIdentifier:#"addListItem"]; // addListItem is storyboard id for viewcontroller
[self presentViewController:advc animated:NO completion:^{
advc.vc = self; // here vc is the propery of type `UIVIewController` declare in AddListItemVC
}];
Now your code for going to details VC from add list VC should be like,
DetailListViewController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"detailViewScreen"]; // detailViewScreen is storyboard id which you can set from identity inspector
[self dismissViewControllerAnimated:NO completion:^{
[self.vc.navigationController pushViewController:dvc animated:YES]; // here self.vc is global variable or property that contains reference of first VC (i.e. list view controller)
}];
no need to use performsegue in this case. You can use performsegue to go in detailvc directly from firstvc i mean from list vc.
Hope you got understand concept and i have written objective c snippet because of lake of time!! hope you can easily convert to swift!!
Firstly, As you say that addVC is modally presenting so make sure addVC have some navigation otherwise you'll not able to push listItemVC from addVC.
Now second thing, when you're modally presenting addVC then push listItemVC pushed from addVC, now addVC navigation controller have two view controllers. When you call navigationController?.popToRootViewController(animated: true) this will bring you to addVC because is being presented thats's why you will not able to see listVC.
To solve this you've to add some dismiss presented view controller whenever you'll arrive at addVC.
My issue is that I have two view controllers, and I need to transfer a string from one view controller to the next. I already have that down from a segue. The actual issue is that I need a label to change in the next view controller to make it match the currentTitle of the button in the previous view. And yes, there are multiple buttons.
My code from view 1 is this:
#IBAction func whichButtonWasClicked(sender: AnyObject) {
clickedButton = sender.currentTitle!!
}
// Segue - Pass the Data of which lesson was chosen
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestViewController : Lesson = segue.destinationViewController as! Lesson
DestViewController.lessonPlan = clickedButton
}
I connected all my 7 buttons to that same one action.
The problem is that when I transfer view controllers, and do...
print(lessonPlan)
It does not give me the title of the button from the action, because I guess that action is after the segue. And yes I tested it, and it IS after the segue. SO it does work, it's just a bit delayed, and I need it to be a part of the segue.
Since your IBAction is being called after prepareForSegue, you can use programmatic segues.
Right now, you're probably dragging a segue from your button to the next view controller. Instead, you can drag a segue from the current view controller to the next one (see this answer for a visual guide). This will create a programmatic segue that you can trigger whenever you'd like from code. Remember to give the segue an identifier in Xcode.
Then in whichButtonWasClicked, call self.performSegueWithIdentifier("identifier you setin Xcode", sender: sender) after you set clickedButton in order to trigger the segue. By doing so, you'll ensure that your button action is called before the segue starts.
I use a push segue to transition from a uisearchcontroller located within my root view controller, to a second view controller. When I try to use an unwind segue method to transition back to the root view controller from my second view controller, my app does not transition unless the button connected to the unwind method is pressed twice. The unwind method is called both times, however the transition only occurs upon the second call. I do not know why this occurs. Any help is appreciated. Thanks!
Unwind segue method
#IBAction func saveWordAndDefinition(segue:UIStoryboardSegue) {
self.searchController.active = false
if let definitionViewController = segue.sourceViewController as? DefinitionViewController {
saveWordToCoreData(definitionViewController.word)
}
tableView.reloadData()
}
How I linked my segue
Unwind segue
While what you're doing is permissible, it seems to be against best practice. The functionality of presenting a view controller, UITableViewController in this case, entering information, then later dismissing it with a button in the upper-right hand corner is generally associated with a modal view. In a push segue you'll get the back button in the upper-left corner for free, which will enable to you to pop the view controller off the stack without writing extra code.
Here's another Stack Overflow question that describe: What is the difference between Modal and Push segue in Storyboards?
To answer your question specifically, here are a couple links that should help:
[self.navigationController popViewControllerAnimated:YES]; is probably what you're looking for.
Dismiss pushed view from within Navigation Controller
How can I dismiss a pushViewController in iPhone/iPad?
So here's how I finally got this to work:
In my FirstViewController (the vc i'm unwinding to):
Here is my unwind segue method.
#IBAction func saveWordAndDefinition(segue:UIStoryboardSegue) {
self.navigationController?.popViewControllerAnimated(false)
}
Then I gave my unwind segue the identifier "unwind" in Storyboard.
In my SecondViewController (the vc i'm unwinding from):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "unwind" {
if let destination = segue.destinationViewController as? VocabListViewController {
destination.saveWordToCoreData(word)
destination.tableView.reloadData()
}
}
}
I took care of passing data in the prepareForSegue method of my SecondViewController. Thanks to #Lory Huz for the suggestion. I finally figured out what you meant by it.
Works without any errors!
Im using StoryBoard and i am not so sure how to instantiate a ViewController or how to reference one.
The thing is i have two view controllers and i have one with a button. I want to go to the other view controller when i pressed the button from the first view controller.
I have tried something like that:
let secondViewController:UIViewController = UIViewController()
self.presentViewController(secondViewController, animated: true, completion: nil)
Does anyone knows how to explain it to me? Thanks!
There are couple of ways of navigating between view controllers. Here's how you do it in code without segues if you're going that way.
Presenting a view controller modally.
Say you have 2 view controller scenes in the storyboard, FirstViewController and SecondViewController. You want to transit from FirstViewController to SecondViewController and there is no segue between them.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyboard.instantiateViewControllerWithIdentifier("SecondVC") as UIViewController
presentViewController(secondViewController, animated: true, completion: nil)
The important part is the that you have to assign an identifier to the view controller you want to go. In this case its the SecondViewController. The way you assign an identifier is you select the view controller, open up the right panel and in it, go to the Identity Inspector (the third one from the left) and under the Identity, assign an identifier to the Storyboard ID field. I put mine as SecondVC as you can see from the code snippet above.
Push to another view controller.
If you want to push on to another view controller instead of presenting it, all you have to do is embed the FirstViewController in a UINavigationController and change the code to this.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyboard.instantiateViewControllerWithIdentifier("SecondVC") as UIViewController
navigationController?.pushViewController(secondViewController, animated: true)
In a comment of yours I saw you want to go to the next view controller based on a condition. Well all you have to do is check your condition in a if else statement and execute either of those above code.
Using Segues.
If you're going to use segues instead of code, here's how you do it.
In the storyboard first you select the button and Ctrl drag to the other view controller. You'll be prompted to choose between different segues. Select show for push or show detail for modal transition (I've explained what these are below). And that's it! If you run it and tap the button, you'd be taken to the other view controller.
But if you want more control over this, you have to do a little more work.. Instead of creating a segue directly from the button, select your view controller and select that little yellow icon on top (This is in Xcode 6. In older Xcode versions its under the view controller scene). Ctrl drag from that icon to the other view controller you want to transit to. You can see a connection appears between those two controllers. Select the segue and open up the right panel and go to the Attributes Inspector (The forth one from the left). Give a name to the field identifier. I gave ToSecond.
Now create a normal action from the button. And you have to call a method called performSegueWithIdentifier passing that identifier. What it does is basically execute a segue with the identifier we give.
#IBAction func segueButtonPressed(sender: UIButton) {
performSegueWithIdentifier("ToSecond", sender: nil)
}
And this would work. You can do the conditions checking here inside a if else and if the conditions are met, call performSegueWithIdentifier.
One other thing you're likely to face is having multiple buttons in a view controller and segueing to different view controller when you tap each of them. A method called prepareForSegue fires each time a segue happens. And inside it, you can check for current segue identifier and execute it. The below code snippet will make this clearer.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ToSecond" {
let secondViewController = segue.destinationViewController as SecondViewController
}
}
Another thing I'd like to mention is that presentViewController and pushViewController are deprecated from iOS8. Instead you can use showDetailViewController for modal and showViewController to push.
showDetailViewController(secondViewController, sender: nil)
navigationController?.showViewController(secondViewController, sender: nil)
I'm not sure if these are backwards compatible. Meaning using show and show detail will work if you're developing for iOS 7 as well. If you are then just stick with the older methods.
First set seques of uistoryboardviewcontroller and try this
self.performSegueWithIdentifier("push", sender: self)
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "push" {
}
In the storyboard, select VC1 and then select the button and press control and while holding down the left button or touchpad drag across to your VC2. Then a menu should pop up. Select modal.
Run and Test. It should now perform a transition.
To transition back, the easiest way is to embed VC1 in a Navigation Controller. To do this, zoom out, select VC1 and go to the top of the screen and select:
Editor > Embed > Navigation View Controller.
Now test and run. You should have the option to go back.
If you are binding view controller programmatically you need to follow this step if you are creating storyboard based application.
It is similar what we don in Objective-c just the syntax has changed.
According to your question what you need to do is go to Main.storyboard and need to select identity inspector.
There you will be able to view identity which contains two fields
1.) Storyboard ID
2.) Restoration ID
Give them the name of view controller you have binded with class in storyboard id and select check box below restoration id. It will automatically copy storyboard ID in restoration ID.
You need to do same for all your view controllers.
let secondView = self.storyboard?.instantiateViewControllerWithIdentifier("SecondViewController") as SecondViewController
self.presentViewController(secondView, animated: true, completion: nil)
you need to write the name you have entered in Storyboard ID for self.storyboard?.instantiateViewControllerWithIdentifier("/* Storyboard ID */")
You can also visit the link:
Instantiate and Present a viewController in Swift
okay,
in interface builder control click on your button and drag the blue line that appears to the second view controller. The second view controller will highlight blue. You can release and the button is connected. In the popup menu select "modal segue". No code necessary. XCODE handles it.
Watch this video for a demo.