Solved

iOS: Firing a segue programmatically

Posted on 2016-07-16
7
100 Views
Last Modified: 2016-07-19
I am creating an iOS app in Swift. I have a table view with two cells, and want to navigate to another view controller when the user clicks on one of the cells. In storyboard, to create a new segue, I control + dragged from Prototype Cell to the destination view controller. This automatically created the segue, and everything is working fine.

The problem is that I have two cells in the table (Repeat and Snooze). When the user clicks Repeat, it should take them to the Repeat View Controller, when the user clicks the Snooze cell, it should take them to the Snooze View Controller. So to handle this, in addition to the above mentioned "automatic" segue, I am also manually handling firing of Segue in didSelectRowAtIndexPath().
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        if (indexPath.item == 0)
        {
            performSegueWithIdentifier("repeatDaysSegue", sender: indexPath.item)
        }
        else if (indexPath.item == 1)
        {
            performSegueWithIdentifier("snoozeSegue", sender: indexPath.item)
        }
    }

Open in new window

It seems to be working OK, but now when the user clicks on the Repeat cell, you can see two Segues happen in the UI. Also, prepareForSegue() gets fired twice. First time the sender is a UITableViewCell, second time sender is Int.

The class code is below, what am I doing wrong?

class AddEditAlarmViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

	let array = ["Repeat", "Snooze"]

	override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return array.count;
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("settingsCustomCell")! as UITableViewCell
        cell.textLabel?.text = array[indexPath.item]
        return cell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        if (indexPath.item == 0)
        {
            performSegueWithIdentifier("repeatDaysSegue", sender: indexPath.item)
        }
        else if (indexPath.item == 1)
        {
            performSegueWithIdentifier("snoozeSegue", sender: indexPath.item)
        }
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if (segue.identifier == "repeatDaysSegue")
        {
            let cellItem = sender as! Int
            if (array[cellItem] == "Repeat")
            {
                let repeatDaysView = segue.destinationViewController as! RepeatDaysTableViewController
                repeatDaysView.alarm = currentAlarm
            }
        }
    }
}

Open in new window

0
Comment
Question by:pzozulka
  • 3
  • 3
7 Comments
 
LVL 19

Expert Comment

by:Shahan Ayyub
ID: 41714879
Perhaps you did defined segues multiple times for the same cell. Click on view controller from the view hierarchy and go to connection inspector to identify them.
0
 
LVL 8

Author Comment

by:pzozulka
ID: 41714894
There's only a single segue showing in the inspector.
0
 
LVL 9

Expert Comment

by:lisfolks
ID: 41718122
Per your description, @pzozulka, you have one segue defined in the storyboard - yet, you have two potential segues you want to happen (repeatDaysSegue and snoozeSegue). Which is named in the storyboard, and where do you instantiate the 2nd one?
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 8

Author Comment

by:pzozulka
ID: 41719776
Disregard the snoozeSegue, the point of that was to show that there could be potentially many segues created in the storbyboard. But I think that's the root of my question. How do you create multiple segues on tableview. In other words, how do you specify that if cell A is selected, I want View Controller A to be the destination segue, if cell B is selected, I want View Controller B to be the destination.

Right now, for cell A, it's working, but it's happening twice. Seems like once from the storyboard, and the second time from the code. How do I only make it happen once?
0
 
LVL 9

Expert Comment

by:lisfolks
ID: 41719988
It appears you can only have two segues on a table row: one for tapping its accessory button, and one for tapping the rest of the row. See View Controller Programming Guide for iOS: Using Segues

What you can do, though, is set up your segue entirely in code. Delete the automatic segue. Drop everything in prepareForSegue. Then, set up the segues from your didSelectRowAtIndexPath method:
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        if array[indexPath.item] == "Repeat"
        {
            let destViewController = storyboard?.instantiateViewControllerWithIdentifier("repeatDaysView") as! RepeatDaysTableViewController
	          destViewController.alarm = currentAlarm
	          presentViewController(destViewController, animated: true, completion: nil)
        }
        else if array[indexPath.item] == "Snooze"
        {
            let destViewController = storyboard?.instantiateViewControllerWithIdentifier("snoozeView") as! RepeatDaysTableViewController
	          // setup for snooze view...
	          presentViewController(destViewController, animated: true, completion: nil)
        }
    }

Open in new window


You might consider using a `switch` statement, rather than an `if`, if you're going to have several different cases.

As for the dual results from your current segue... I am able to replicate that situation in one of my projects. It's a learning project where I have three options, one leading to a code-only segue, one leading to a manual segue, and one leading to an automatic segue.

The manual segue is like yours, with a storyboard segue and the code call to performSegue... The automatic segue has no performSegue call, but does have action in prepareForSegue. When I change the sender to an Int value, the manual version works fine, but the automatic segue does two calls - just as you're experiencing.

Something is definitely different between the two, but I don't know what. In the storyboard, the automatic segue has a Peek & Pop attribute. The manual segue doesn't have that attribute. I remember creating them differently at the time, but... There's nothing else different in the storyboard. Hmm...

Anyway, the programmatic segues would be best in your situation because you want to do multiple from the same place with different segues (update: not identifiers, just different segues; when you do them programmatically as I described, you're not giving them identifiers).
1
 
LVL 9

Accepted Solution

by:
lisfolks earned 500 total points
ID: 41720159
Got the duplicate segue figured out!

You've got a segue going straight from your table cell to the next view controller. That's a fully "automatic" segue. You can intercept it in prepareForSegue in order to set properties, etc, if necessary. However, you don't need to do a performSegue action because that'll happen automatically when the cell is selected.

Once you added the performSegue call, iOS now does two segues: the automatic segue (giving you the TableViewCell as sender) and the manual segue (giving you the Int provided in the performSegue call).

If you want to do the performSegue call as you have it:
- delete the "repeatDaysSegue" segue currently in your storyboard.

- recreate the segue, with the same ID - but this time, take it from the view controller to the RepeatDaysTableViewController (rather than the table cell to the RepeatDaysTableViewController).

- keep the rest of your code as you have it.

Your performSegue call, then, will only run once as expected. Additional benefit: you can do many segues off your view controller, rather than being limited by directly segueing (is that a word?) from the table cell.
1
 
LVL 8

Author Closing Comment

by:pzozulka
ID: 41720161
Thanks. That's exactly it.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Preface   In the first 100 days of the Macintosh release in January 1984, Apple sold 72,000 of the computers. Relatively cheap, easy-to-use personal computer with a graphical operating system. I've never seen this model. I did see this one:   …
I recently went through the process of creating an installable image of an iPhone mobile app (an .ipa file) that beta testers could load onto their test devices. The process involved quite a few steps, but both Appcelerator and Diawi.org had decent …
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now