Conditional segue performed on tap on UITableViewCell
Asked Answered
D

4

39

I'm working on some project for iOS 5 using Xcode 4.2. I have one UITableViewController and want to perform a segue when user tap on table cell, but destination view controller depends on action performed on that cell. For example, when user tap on cell I would like to load SomeViewController, but when user tap on the same cell in editing mode I would like to load AnotherViewController. Unfortunately, there is no way to configure multiple segues on same cell in Xcode 4.2 storyboard builder, or I just don't get it. Perhaps there is a way to create segue by hand, in code editor. Generally what I want to achieve is to provide user a way to "enter" the item represented by cell using one view controller and "edit" the item represented by the same cell using another view controller. Switching to the second view controller (editor) when in table-edit-mode only was my first though, but maybe there is a better way. Any help will be appreciated.

Daft answered 30/10, 2011 at 2:25 Comment(3)
I've just figured it out. It simple, and can be done using Xcode storyboard editor. I've added two segues to my TableViewController pointing to different view controllers, and I'm triggering proper one from code when user selects a cell, and depending on it is done in editing mode or not - I'm triggering proper segue. Earlier I've tried to add multiple segue to same cell witch is not possible.Daft
It would be nice if you elaborated on this into an answer, showing exactly how you set the segues.Elfland
Refer : #7820296Seddon
K
54

While looking Storyboard, control-drag from your source View Controller to your Destination view controller. This will create a segue that you can trigger programmatically right from your source View Controller. Ensure that you give you Segue a name. This name is what you will pass into the source View Controller's performSegue:withIdentifier: method.

Kinakinabalu answered 22/11, 2011 at 22:3 Comment(2)
The bit that's often missed in the answers I've seen to this question is how to detect the touch that ordinarily triggers the segue now that you've detached it from the cell. The answer is to implement tableView:didSelectRowAtIndexPath: in your UITableViewController - even if it's a static table view. In the body for that method, you put your conditional code and call performSegue:withIdentifier: when conditions are rightItinerary
The point is that you can setup more than one segue from a tableView prototype cell. Just give them distinct identifiers. That way in your didSelectRowAtIndexPath: you can set a condition if ([self.tableview isEditing]) and cause the segue in using the identifier you set up.Derickderide
I
33

I'm adding an extra answer just because after reading the selected one above in many places other than this - and it is the correct answer - I found myself wondering how to detect the touch that would ordinarily trigger the segue. You see, if you create your segue the usual way by ctrl-dragging from the table view cell to the next controller, then two things are done for you automatically.

  1. the touch in the cell is detected
  2. the segue is performed

but of course, you can't block the segue.

Now if you want to conditionally segue, then (as mentioned in the other answers) you delete that segue and create a new one from the UITableViewController (drag it from the objects navigator rather than the storyboard) to the next controller - and give it a name.

Then - and this is the part I was missing - implement tableView:didSelectRowAtIndexPath in your table view controller to perform the segue programmatically and conditionally, as below.

Note that you also need to identify your cell somehow so you know if the one you're interested in has been selected. You could do that by knowing the index path in a static table, but I prefer to set my cells unique identifier in IB (even though I don't need it for dequeueing since it's a static table) and checking it. That way if I move my cell up or down in the static table, I won't need to change this code.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Find the selected cell in the usual way
    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

    // Check if this is the cell I want to segue from by using the reuseIdenifier
    // which I set in the "Identifier" field in Interface Builder
    if ([cell.reuseIdentifier isEqualToString:@"CellIWantToSegueFrom"]) {

    // Do my conditional logic - this was the whole point of changing the segue
    if (myConditionForSegueIsSatisfied) {
        // Perform the segue using the identifier I was careful to give it in IB
        // Note I'm sending the cell as the sender because that's what the normal
        // segue does and I already had code counting on that
        [self performSegueWithIdentifier:@"SegueIdentifer" sender:cell];
    }
}

Note how I send the cell with the segue - the normal segue from the cell does that, and I had originally passed nil, and my code which had depended on it stopped working.

Itinerary answered 1/11, 2012 at 12:46 Comment(0)
T
5

This is an old question and some great correct answers but I'll post some additional information I felt helpful when I encountered this:

  1. If you create a segue in the storyboard by ctl+drag from SomeVC to AnotherVC, delete it.

  2. In the object navigator, ctl+drag at the ViewController level (usually first in the hierarchy under the name of the VC) from SomeVC to AnotherVC. Give the segue a unique identifier.

  3. Implement tableView: didSelectRowAtIndexPath: as described above.

  4. I found it helpful to use a switch statement in tableView: didSelectRowAtIndexPath:

    switch (indexPath.row) {
    case 0:
        [self performSegueWithIdentifier:@"yourIDHere" sender:self];
        break;
    case 1:
        // enter conditional code here...
        break;
    case 2:
        // enter conditional code here...
        break;
    // ... for however many cells you require
    
    default:
        break;
    

    }

Thanks for the great answers everyone.

Thong answered 11/3, 2015 at 22:22 Comment(0)
P
1

You can easily control opening of any segue in your custom UIViewController by implementing:

override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { return true // or false, depending on what you need }

Peddle answered 15/2, 2016 at 19:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.