前语

Swift 中的枚举很强大,算是一等公民。能够界说函数,也能够恪守协议、完成 extension 等等。

相关值也是 Swift 枚举的一大特性。根本用法如下:

enum RequestResult {
    case success
    case failure(Error)
}
let result = RequestResult.failure(URLError(URLError.timedOut))
switch result {
case .success:
    print("请求成功")
case .failure(let error):
    print(error)
}

1、在需求相关值的 case 中声明相关值的类型。

2、在 switch 的 case 中声明一个常量或者变量来接收。

遇到的问题

一般状况下,上述的代码是明晰明了的。但在实践开发的过程中,遇到了以下的状况:相关值的类型也是枚举,并且嵌套不止一层。

比方下面的代码:

enum EnumT1 {
    case test1(EnumT2)
    case other
}
enum EnumT2 {
    case test2(EnumT3)
    case other2
}
enum EnumT3 {
    case test3(EnumT4)
    case test4
}

依据咱们的需求,需求进行屡次嵌套来进行类型细化。当进行枚举的声明时,代码仍是正常的,简单明了。但当进行 case 判别时,代码就变得丑陋难写了。

比方,我只想处理 EnumT3 中的 test4 的状况,在 switch 中我需求进行 switch 的嵌套来处理:

let t1: EnumT1? = .test1(.test2(.test4))
switch t1 {
case .test1(let t2):
    switch t2 {
    case .test2(let t3):
        switch t3 {
        case .test4:
            print("test4")
        case default:
            print("default")
        }
    default:
        print("default")
    }
default:
    print("default")
}

这种写法,对于一个程序员来说是无法忍受的。它存在两个问题:一是代码臃肿,我的本意是只处理某一种状况,但我需求显式的嵌套多层 switch;二是枚举本身是不引荐运用 default 的,官方引荐是显式的写出一切的 case,以防呈现难以预料的问题。

废话不多说,下面开始简化之路。

实践一

首先能想到的是,由于是对某一种状况进行处理,考虑运用 if + == 的判别来进行处理,比方下面这种写法:

if t1 == .test1(.test2(.test4)) { }

这样处理有两个不足之处。首先,假如对枚举用 == 操作符的话,需求对每一个枚举都恪守 Equatable 协议,这为咱们带来了工作量。其次最重要的是,这种处理方式无法应对 test3 这种带有相关值的状况。

if t1 == .test1(.test2(.test3) { }

假如这样写的话,编译器会报错,由于 test3 是需求传进去一个 Int 值的。

if t1 == .test1(.test2(.test3(20))) { }

假如这样写的话也不可,由于咱们的需求是处理 test3 的统一状况(一切的相关值),而不是某一个详细的相关值。

实践二

通过在网上的一番搜寻,发现能够用 if-case 关键字来简化写法:

if case .test1(.test2(.test3)) = t1 { }

这样就能统一处理 test3 这个 case 的一切状况了。假如想获取相关值,能够用下面的写法:

if case .test1(.test2(.test3(let i))) = t1 {
    print(i)
}

比照上面的 switch 写法,能够看到,下面的这种写法既易懂又好写。

总结来说,当咱们遇到相关值多层枚举嵌套的时候,又需求对某一种状况进行处理。那么能够选用实践二的做法来进行代码简化。

参考链接

  • 官方文档
  • stackoverflow