So I have been trying to get a unwind segue to work from last two days. I have tried watching and follow several different tutorials and none was successful. I created the #IBAction override func unwind(for unwindSegue: UIStoryboardSegue, towardsViewController subsequentVC: UIViewController) but this never performs any of the code. I put a simple print and had it print text, it never printed the text. I created that in the first View Controller then in the second View Controller I had a button that I connected to the Exit at the top of the View Controller and selected the unwind action and it never unwinds. What am I doing wrong or missing?
So here is what I have so far I have 2 views: RaceViewController & SingleStatViewController
I will start by selecting specified rows in RaceViewController and they will open SingleStatViewController modally. I have a button in SingleStatViewController called dismissBtn. When I click the button it dismisses SingleStatViewContoller. I just need it to pass some data back to the RaceViewController.
So if the user selects 1 of 3 cells in the table (the rows are Half-Orc, Half-Elf and Human) it will open SingleStatViewController and ask to select 1 stat (these will be of 6 buttons (Str, Dex, Con, Int, Wis, Chr) when they select the one of the buttons it will return the data and update the detailTextLabel.
I select Human then I select Str. When it gets back to RaceViewController and it updates the text in the detailTextLabel to +2 Str.
Right now, this is the code I am using to dismiss. Can I use this to continue or do I actually need to perform the unwind:
#IBAction func dismissbtn(_ sender: Any)
{
dismiss(animated: true, completion: nil)
}
You need to perform unwind and send data as following:
#IBAction func unwindToRaceViewController(sender: UIStoryboardSegue)
{
if let sourceViewController = sender.sourceViewController
as? RaceViewController {
stat = sourceViewController.stat
}
You could refer to this article for unwind segues as alternative to delegate
You could also use delegates to pass data back to the previous controller.
Okay, so you have vc A and vc B, this is what you need to do to use unwind segue:
In vc A, create a segue function eg. #IBAction func unwind(segue: UIStoryboardSegue)
In vc B, write code that call self.performSegueWithIdentifier("unwind", sender: self) (assume that the identifier and the function name is the same - call this in your dismissbtn)
In vc B in storyboard, look on top of it, there will be an yellow button and 2 orange button, hold and drag the yellow button to the Exit orange button, choose the action that you created in vc A, give it an identifier as mentioned
In the unwind func, the rest is the same as normal segue when you pass data forward, just change destination to source and you must present vc B from vc A, else then use delegate
Related
Setup:
Initial view controller A has a menu button that goes to VC B, which then has a button that goes to VC C. On C, I have an exit button that takes me back to A. In this transition, B briefly appears. The two things I'm trying to figure out is:
How do I keep B from flashing on the screen?
and
Is B off the call stack and releasing the memory?
This is what I'm running to get rid of the C and go back to A:
#IBAction func backButtonPressed(_ sender: Any) {
self.view.window!.rootViewController?.dismiss(animated: true, completion: nil)
//performSegue(withIdentifier: "exitToMainScreen", sender: self)
}
I found a work-around for this glitch.
In VC B, I encapsulated everything in a view attached to an outlet. So when I perform the segue to VC C, I set the view's isHidden = true. When the unwind from C to A occurs, the view in B is hidden and does not appear on the screen in transition.
So here's my problem.
First ViewController has some fields regarding name, date, no. of people of an Event (the user creates and event). It also has a button that will transition the user to a new viewController with a mapView where user will create a Pin. After user creates a Pin, user can press the pin (or do some other action that confirms that the Pin user put on the map is correct) and user will be transitioned to a new tableViewController with multiple locations near the Pin he selected (using Foursquare API).
Then the user must be transitioned to the first ViewController. The Location user tapped must be sent to the first ViewController.
This is my first time working with multiple ViewControllers and I need your help.
How would I do this (don't miss on any details please :D) ?
Use an unwind segue to pass data backwards through view controllers embedded in a navigation controller.
Here's a brief example.
In your first view controller you can have something like:
var text: String?
#IBAction func unwindSegue(segue: UIStoryboardSegue) {
if let viewController = segue.sourceViewController as? ViewController2 {
text = viewController.textField.text
}
print(text!)
}
Add the unwind segue in the second view controller on the storyboard by ctrl-dragging from the view controller (yellow circle with a square in, to the exit icon (either at the top of the view controller or in the document outline) and click on the unwind segue that you created to create a manual segue. Then in the document outline set the unwind segue's identifier so that you can refer to it (I've called it simply "Unwind" for this example).
In the second view controller (the one you want to pass back from) add this:
#IBOutlet var textField: UITextField!
#IBAction func backButton(sender: AnyObject) {
self.performSegueWithIdentifier("Unwind", sender: nil)
}
This simple example will let you pass back the text from the textField in your second view controller.
n.b. You can unwind more than one view at a time.
So I have a page view controller setup and each of my pages has a back button that calls an unwind segue which when arriving at the root page controller calls another unwind segue to get back to the main menu:
func backButtonAction(sender:AnyObject!){
println("ok")
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("unwindGameContentViewController", sender: self)
}
//self.performSegueWithIdentifier("loadFollowPatternViewController", sender: self)
//self.performSegueWithIdentifier("unwindGamesContentViewController", sender: self)
}
and
#IBAction func unwindToViewController(sender:UIStoryboardSegue){
println("blow")
self.performSegueWithIdentifier("unwindGamesViewController", sender: self)
}
On the first page clicking the back button functions as usual but then the second and third page of the view controllers do not function at all. The backButtonAction function is called and the ok is printed but the unwind does not take place and the blow print line is not printed either.
I get no errors or warnings about storyboard or anything else.
My code used to work before Xcode 6.3 came out with the updated swift language, however I am not sure whether I broke the code before then or the update broke it.
I would like to know if it is possible to assign two different unwind method at the same button. For example:
I have this views navigations:
Home->A->B
Home->C->B
A and C views navigates to B, but then I want to return to previous views using the same B view and controller.
It is possible?
I have been thinking about write assign unwind method to the button programmatically depending what view comes.
Thanks in advance
I'm sorry about my english, is not good.
Here's a Swift solution that worked well for me. The code below only works if you hookup your segues correctly in the storyboard and in code. Checkout this page for great explanations on setting up unwind segues.
In summary:
You're accessing the same view from multiple other views. So, when you segue to a view, you can pass the source view controller (the view that you're currently in) to a property in the view that you're going to.
In your view that you will unwind out of, you can check the property holding the info (the class) on where you came from, and then perform a segue based on what view it is.
The code: (using ex: Home -> A -> B or... Home -> C -> B)
Note: B is the view that will unwind to multiple different views.
In A or C: (code works the same way in both views)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueIdentifierInViewAthatGoesToViewB" {
let controller:B = segue.destinationViewController as! B
//the code below passes our current view controller class to a property in view B.
//So, view B will know what view we came from.
//In our example, we're coming from view A or C
controller.viewControllerNavigatedFrom = segue.sourceViewController
}
}
In B:
//setup an IBAction that will check the source view controller (that we passed when we segued to this view) and perform a segue based on where we came from. You can hook this up to a button or anything you want really.
//isKindOfClass(A) - "A" would be the name of your class
//setup a property to receive the view controller class where we are coming from
var viewControllerNavigatedFrom:AnyObject?
#IBAction func myButtonPressed(sender: AnyObject) {
if self.viewControllerNavigatedFrom!.isKindOfClass(A) {
//Unwind to view A
performSegueWithIdentifier("unwindFromBbackToA", sender: sender)
}
else if self.viewControllerNavigatedFrom!.isKindOfClass(C) {
//Unwind to view C
performSegueWithIdentifier("unwindFromBbackToC", sender: sender)
}
}
Although, question isn't very clear. But what I could understand is that you want to navigate back to the previous view i.e. B>C or B>A depending upon where user came from.
If so, then check the UINavigationController. It keeps track of the navigation history and automatically adds a back button. Kind of like the back button in our browsers.
Here is a tutorial, although a bit old: Link
#IBAction func unwindOtherVw (seque: UIStoryboardSegue) {
println("the objectfromOtherView is \(objectFromOtherView!)")
}
I'm passing an object (NSManaged) from the other ViewController using prepareForSeque method and exit in the storyboard along with the code above in the destination controller. All is working fine, but how can I add an identifier to the unwind segue so that prepareForSegue could use if seque.indentifier == ______
You should be able to see the unwind segue in the tree view of components on the left. YOU can select it and add an identifier in the attributes inspector.
eg: