0

In my first section I show different style UIAlertController based on the row. Second section does unrelated stuff. In order to avoid code duplication in both cases, how do I fallthrough to a specific case in switch statement? Is this possible in swift? Does any other language have this concept?

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
    var alertController: UIAlertController!
    let cancelAction = UIAlertAction(title: L10n.Cancel.localized, style: .Cancel) { (action) in
        // ...
    }
    switch (indexPath.section, indexPath.row) {
    case (0, 0):
        alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
        //add other actions
    case (0, 1):
        alertController = UIAlertController(title: nil, message: nil, preferredStyle: .Alert)
        //add other actions
    case (0, _): //this case handles indexPath.section == 0 && indexPath.row != 0 or 1
        //I want this to be called too if indexPath.section is 0;
        //even if indexPath.row is 0 or 1.
        alertController.addAction(cancelAction)
        presentViewController(alertController, animated: true, completion: nil)
    default:
        break
    }
}
osrl
  • 8,168
  • 8
  • 36
  • 57
  • Actually it's not possible. You can only `fallthrough` to consecutive cases. Use a second switch or the classic `if - else` expression. – vadian May 05 '16 at 17:58

2 Answers2

1

What you are trying to achieve currently doesn't seem to be possible with Swift switch statements. As mentioned in another answer by @AMomchilov

switch statements in Swift do not fall through the bottom of each case and into the next one by default. Instead, the entire switch statement finishes its execution as soon as the first matching switch case is completed, without requiring an explicit break statement.

The fallthrough keyword also doesn't seem to solve the problem, since it won't evaluate the case conditions:

A fallthrough statement causes program execution to continue from one case in a switch statement to the next case. Program execution continues to the next case even if the patterns of the case label do not match the value of the switch statement’s control expression.

I think that the best solution would be to have something like

switch (indexPath.section, indexPath.row) {
case (0, _):
    if indexPath.row == 0 {
        alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
    }
    alertController = UIAlertController(title: nil, message: nil, preferredStyle: .Alert)
    alertController.addAction(cancelAction)
    presentViewController(alertController, animated: true, completion: nil)
default:
    break
}
romants
  • 3,660
  • 1
  • 21
  • 33
  • Does any other language has this concept of re-evaluating the case conditions? – osrl May 05 '16 at 18:29
  • AFAIK, I don't think that any other language has that concept, especially compiled ones, since in assembly that requires quite messy code that would go back and re-evaluate the condition after each block – romants May 05 '16 at 20:00
  • The assignment in the if statement body gets clobbered on the next instruction. – Alexander May 09 '16 at 17:43
-1

You use the fallthrough keyword.

No Implicit Fallthrough

In contrast with switch statements in C and Objective-C, switch statements in Swift do not fall through the bottom of each case and into the next one by default. Instead, the entire switch statement finishes its execution as soon as the first matching switch case is completed, without requiring an explicit break statement. This makes the switch statement safer and easier to use than the one in C and avoids executing more than one switch case by mistake. -The Swift Programming Language (Swift 2.2) - Control Flow

However, the fallthrough keyword can only be used to add on functionality. You can't have the first and second case be mutually exclusive, and also fallthrough to the third case. In your situation would refactor the common case to occur unconditionally after the switch statement, and change the default case from break to return.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • 1
    This will not work, the question is about specific case, i.e. falling from 1st switch to 3rd – romants May 05 '16 at 17:18
  • reorder the statements, then – Alexander May 05 '16 at 17:19
  • yeah, both 1st and 2nd seem to need to fall through to 3rd – romants May 05 '16 at 17:20
  • That's not fallthrough then. Fallthrough can only add on functionality. This is a job for GOTO, which Swift doesn't support. The `presentViewController(alertController, animated: true, completion: nil)` line can be moved after the switch statement, with the default case `return`ing instead of `break`ing – Alexander May 05 '16 at 17:22
  • @osrl, isn't that what I was saying when trying to correct the answer? – romants May 05 '16 at 17:24
  • swift has label statements but it won't work here I think – osrl May 05 '16 at 17:24
  • Sorry @RomanTsegelskyi wrong mention :) Thank you for clearing it for me. – osrl May 05 '16 at 17:26