Connect performSegue w/ prepareForSegue in Swift - ios

Sorry for the vague title, I've never been really good with words but this is the general outline of what I want to do.
I have two view controllers,
-One called settings
-One called setDate
In the settings view controller I have two buttons, one called 'summary time', the other called 'daily time'
Each are linked to different IBActions that segue to the setDate view controller using performSegue.
My question is how could I perform an if statement in the setDate view controller by comparing the sender that performed the segue?
Sorry if I don't make much sense but could anyone help me?

You normally configure the 'setDate' view controller in the 'prepareForSegue' method of the 'settings' view controller. Something like this:
class SettingsViewController : ... {
// ...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueSummaryTime" {
let dest = segue.destinationViewController as SetDateViewController
// configure dest for 'summary time'
// for example:
dest.isForSummary = true
// ...
}
else if segue.identifier == "segueDetailTime" {
// as above but for 'detail time'
}
}
// ..
}
For the above, you should have linked each button to a different segue, each with an identifier as I've illustrated above.

Related

I do not understand what this code does(the code is about segues)

I am watching an iOS course video and the person in the course types up this code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let nextVC = segue.destination as! CreateTasksViewController
nextVC.tasksVC = self
}
The CreateTasksViewController is the view in the project that we are supposed to segue to. Also the "tasksVC" is the current view controller that in the app we are supposed to be on.I do not understand what this code mean and it would be helpful if someone could explain exactly what the function of the code is. Also what is "as!"?If you need any more details regarding my problem, feel free to ask in the comments.
That's not the best segue code. Here's how I'd code it (for the record, there are several ways to code this):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "[segue name here]" {
if let nextVC = segue.destination as? CreateTasksViewController {
nextVC.tasksVC = self
}
}
}
The code you posted has what is called a "forced unwrap" of the segue destination (that's the as! you asked about). Here's a question with a pretty good answer explaining the dangers of forced unwrapping. Scroll down to the divider in the answer.
While I'm sure the code compiles (and likely runs), the problem is code maintenance.
Suppose you have several segues defined between several scenes, each with their own view controller? My code, as matter of style, gives up a bit of "Swiftiness" for "explicitness":
(1) A check is made that the segue is the correct one
(2) An if let... as? is made to safely check if the segue destination if the correct view controller
(3) If everything passes the checks, then the code is executed. In this case, it looks like it passes the entire(!) view controller into a variable called tasksVC in the CreateTasksViewController.
I'm actually cautious about item 3 - why would anyone pass one view controller into another one as a variable? Most cases in prepare(for segue:) one or more variables inside the sending VC are passed to the destination. If I may offer this to you... find another tutorial!

unwind segue pass data to different viewcontrollers

I have an app which have 4 different forms. these forms can be completed by clicking the different questions and being lead to a viewcontroller which holds the options. lets call this the OptionViewController. Now I have 4 different forms with different options but all using OptionViewController to pull data from the database, I need to unwind the segue and pass data.
Since there might be 4 different view controllers it might be coming from, I need to make sure that the information is passed properly, i.e. identify if the destinationviewcontroller the unwindsegue is performing the first, second, third or fourth viewcontroller.
I thought I might do something like this
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "optionSelected" {
if segue.destinationViewController == FirstViewController {
//pass data
} else if segue.destinationViewController == SecondViewController {
//pass data
}
}
}
But obviously I cannot perform segue.destinationViewController == FirstViewController
What should I actually be doing? Or should i just create one OptionViewController for every form, which would solve my problem, but I am not sure if overall the app performance will drop due to the increase of view controllers
Thanks for any help in advance
To test if the destination view controller is of a specific class, use the Swift keyword is:
if segue.destinationViewController is FirstViewController {
Alternatively, you can assign the viewController to a variable using optional binding with an optional cast:
if let dvc = segue.destinationViewController as? FirstViewController {
// dvc will have type FirstViewController so you can access specific
// properties of FirstViewController using dvc
}

UIKit - action when navigation controller did navigate back

This should be absolutely trivial but I can't find anything so:
I have a simple storyboard with navigation controller where I push a view controller, let's call it "Jane", from a view controller called "Bob".
So Bob wants to do something whenever Jane is dismissed after tapping the "back" button, like so:
- (IBAction) janeWasDismissed:(UIViewController *)jane
{
// bob wants to ask what Jane did.
}
It's the simplest thing right? But I can't figure it out, surely Unwind Segues are not the right way?
There must be a simple click & drag operation for this in Interface Builder, or a method on UIViewController which is called when the pushed view controller has popped?
thanks!
Actually it's not at all trivial. If Bob is going to need information from Jane, you need to arrange for Jane to send that information back to Bob. For example, in Jane's viewWillDisappear:, she can get herself a reference to Bob (by way of the navigation controller that they both share) and call some method in Bob.
You might object (quite reasonably) that this implies a knowledge of Bob's class on the part of Jane. The usual solution to that is even more non-trivial: it is that Bob, as he summons Jane, makes himself available to Jane as a delegate cast as a protocol that Jane defines. Thus Jane needs to know only one method of Bob - not his actual class, but the method that she herself has specified in her protocol.
There is no simple click & drag operation for this in Interface Builder.
There is no method on UIViewController which gets called when the pushed view controller has popped.
JaneViewController has to signal BobViewController.
class BobViewcontroller {
var janeWasDismissed = false
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if janesWasDismissed {
// Do something
janeWasDismissed = false
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "go-to-jane" {
let destinationController = segue.destinationViewController as! JaneViewController
destinationController.delegate = self
self.janeWasDismissed = false
}
}
}
class JaneViewController {
var delegate: BobViewcontroller?
func dismissJane() {
if let delegate = delegate {
delegate.janeWasDismissed = true
self.navigationController?.popViewControllerAnimated(false)
}
}
}

Multiple unwind in the same button - Swift

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

Swift - Performing Segue from UITableViewCells to different View Controller Destinations

so I am having issues figuring out how to implement code for the following purpose:
Essentially my app allows a user on the opening screen to type different categories in a UItextfield, hit enter, and then have those categories appear in a UITableView (all on the same initial view controller). For example the user could enter "Friends from home", "College Friends", "NBA Players".
From there, I want the user to be able to drill down on one of the rows, and be taken by a segue to a UITableView controller where they can add names to those lists and ultimately be able to rank them for fun...
But my question currently is once the user has added the groups that he wants on the initial view controller, how does he/she drill down and segue to a SPECIFIC view controller based on the row he/she tapped?
(I want to post a picture of my storyboard but I don't have the necessary 10 reputation points yet!)
I tried code like this but have gotten no results. I will also note that I dragged a show segue from the uitableviewcell on the opening view controller to the UITableViewController (segue is named "EachGroup").
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "EachGroup") {
// pass data to next view
let UIViewController:ViewController = segue.destinationViewController as ViewController
let indexPath = self.tableView.indexPathForSelectedRow()
}
That's not a new question, many topics about.
You should specify a tag on each cell : cell.tag = 0
In your prepareForSegue, use :
if sender!.tag.littleEndian == 0
{
let UIViewController:ViewController = segue.destinationViewController as YourSpecificViewcontroller
}
else if sender!.tag.littleEndian == 1
{
let UIViewController:ViewController = segue.destinationViewController as YourOtherSpecificViewcontroller
}
Hope it helps,
Sidd.

Resources