Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional segue performed on tap on UITableViewCell

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.

like image 439
Darrarski Avatar asked Oct 30 '11 02:10

Darrarski


4 Answers

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.

like image 94
Lemont Washington Avatar answered Nov 18 '22 09:11

Lemont Washington


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.

like image 24
Rhubarb Avatar answered Nov 18 '22 11:11

Rhubarb


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.

like image 5
Chris Holloway Avatar answered Nov 18 '22 10:11

Chris Holloway


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 }

like image 1
vedrano Avatar answered Nov 18 '22 09:11

vedrano