Swift Switch介绍

network | | 访问(68)

根据特定的条件执行特定的代码通常是十分有用的,例如:当错误发生时,你可能想运行额外的代码;或者,当输入的值太大或太小时,向用户显示一条消息等。要实现这些功能,你就需要使用条件语句。Swift 提供两种类型的条件语句:if语句和switch语句。通常,当条件较为简单且可能的情况很少时,使用if语句。而switch语句更适用于条件较复杂、可能情况较多且需要用到模式匹配(pattern-matching)的情境。Switch作为选择结构中必不可少的语句也被加入到了Swift中,只要有过编程经验的人对Switch语句都不会感到陌生,但苹果对Switch进行了大大的增强,使其拥有其他语言中没有的特性。

1、不存在隐式的贯穿(No Implicit Fallthrough)

与 C 语言和 Objective-C 中的switch语句不同,在 Swift 中,当匹配的 case 分支中的代码执行完毕后,程序会终止switch语句,而不会继续执行下一个 case 分支。这也就是说,不需要在 case 分支中显式地使用break语句。这使得switch语句更安全、更易用,也避免了因忘记写break语句而产生的错误。

var i = 0  
switch i {  
    case 0:  
        "0" //被输出  
    case 1:  
        "1"  
    default:  
        "2"  
}

2、一个 case 也可以包含多个模式,用逗号把它们分开(如果太长了也可以分行写)

var i = 3  
switch i {  
    case 0,3:  
        "0" //被输出  
    case 1:  
        "1"  
    default:  
        "2"  
}

3、如果就是想执行完一条case之后,想继续执行下一条case,就要用到一个新的关键字:fallthrough

var i = 0  
switch i {  
    case 0:  
        "0" //被输出  
        fallthrough  
    case 1:  
        "1" //被输出  
    case 2:  
        "2"  
    default:  
        "default"  
}

使用新的关键字fallthrough能使Switch在执行完一个case之后,紧接着执行下一条case。

4、Swift的Switch语句一定要涵盖所有的情况,这并不是说一定要有default,只要上面的case能满足所有的情况,就可以不用写default。

需要注意的地方有两点:

(1)Switch当然也支持显式的break,通常只有一种情况下你会这么做,那就是当你也不想在default里做任何事情的时候,这个时候你就可以在default里显式地加上一句break。

(2)fallthrough并不是在任何情况下都有效,当你在Switch里使用Value Binding技术的时候,fallthrough就被禁止了。Value Binding在下面会讲到。

5、支持多种数据类型

在Objective-C里,Switch语句只能支持整形的数据(或者一个字符),但是在Swift里,Switch能支持多种数据类型,包括浮点、布尔、字符串等:

支持浮点:

let float = 1.5  
switch float {  
    case 1.5:  
        "1.5"   //被输出  
    default:  
        "default"  
}

支持布尔:

let isSuccess = true  
switch isSuccess {  
    case true:  
        "true"   //被输出  
    default:  
        "default"  
}

支持字符串:

let name = "Bannings"  
switch name {  
    case "Bannings":  
        "Bannings"   //被输出  
    default:  
        "default"  
}

可以说是史上支持数据类型最多的Switch了。

6、支持区间匹配(Range Matching)

不仅仅是循环结构里可以用区间运算符,在Switch里同样可以用区间运算符:

var i = 15  
switch i {  
    case 0 ... 10:  
        "0~10"  
    case 11 ... 20:  
        "11~20" //被输出  
    default:  
        "default"  
}

对某个数值区间进行批量匹配,这样是不是很酷?浮点数也同样支持区间运算符。

7、支持元组

作为被大大增强的Switch,元组也是被支持的:

let request = (true,"success")  
switch request {  
    case (true, "success"):  
        "success"   //被输出  
    case (false, "failed"):  
        "failed"  
    default:  
        "default"  
}

使用元组和使用其他数据类型一致,不过元组还有一项特点,对于不想关心的值,可以用下划线_跳过,如:

let (name,  _, age) = ("Bannings" ,true, 22)

那么在使用Switch时,同样支持这项特性:

let request = (true,"success")  
switch request {  
    case (_, "success"):  
        "success"   //被输出  
    case (false, _):  
        "failed"  
    default:  
        "default"  
}

对于不关心的值跳过,只要满足另一个值就行了。需要注意一点的是,如果元组中的值也是数字类型,那么也是可以用区间运算符的:

let request = (10,"failed")  
switch request {  
    case (_, "success"):  
        "success"  
    case (1 ... 10, _):  
        "1~10"    //被输出  
    default:  
        "default"  
}

8、值绑定(Value Bindings)

针对元组,Switch还支持类似于Optional Binding的Value Binding,就是能把元组中的各个值提取出来,然后直接在下面使用:

let request = (0,"success")  
switch request {  
    case (0, let state):  
        state    //被输出:success  
    case (let errorCode, _):  
        "error code is \(errorCode)"  
}  // 涵盖了所有可能的case,不用写default了

这样也是可以的:

let request = (0,"success")  
switch request {  
    case let (errorCode, state):  
        state    //被输出:success  
    case (let errorCode, _):  
        "error code is \(errorCode)"  
}

把let放在外面和放在里面为每一个元素单独写上let是等价的。

当你在一个case里使用Value Binding的时候,如果你同时也在它的上一个case里使用了fallthrough,这是编译器所不允许的。只要把下面的errorCode去掉就行了,当然,考虑好自己的逻辑。

9、支持额外的逻辑判断 Where

在使用Switch语句时,Switch会适当地导向相应的case部分,这其实就相当于做了一次逻辑判断,但Swift的Switch语句还支持额外的逻辑判断:

let request = (0,"success")  
switch request {  
    case (0, let state) where state != "success":  
        state  
    case (let errorCode, _):  
        "error code is \(errorCode)"//被输出:"error code is 0"  
}

这同样很酷,相信在某种情况下会派上大用场。

总结

Swift对Switch进行了大大增强,使Switch的灵活性得到了很大提升,这是激动人心的改变,但是如果掌控不好其中的变化,可能会使你在进行错误排查时增加难度,也会使代码复杂度变高。在适当地时候灵活运用,保持头脑清晰总是有益的。