Swift枚举详解

和结构体一样,swift中的枚举也是值类型。除了定义一个或多个case成员,还可以做以下事情:

  • 可以定义方法,计算属性,下标
  • 可以通过mutating定义可变方法
  • 可以扩展,遵守协议,支持范型

和结构体的唯一区别就是枚举不能定义存储属性
1. 枚举的语法:

enum TextAlignment{
    case left
    case right
    case center
}
//或者 写在一行
enum TextAlignment{
    case left, right, center
}

2. 遵守协议&遍历枚举值

例如:系统自带的CaseIterable协议,allCases属性列出所有的枚举成员,也可以通过手动添加计算属性或方法达到同样的目的,对于没有关联值的枚举,编译器会自动为其实现allCases(成员顺序和声明时候一致)

extension TextAlignment:CaseIterable{}
TextAlignment.allCases // left right center
// 或者 手动添加计算属性
extension TextAlignment {
    static var allCases: [TextAlignment] {
            [.left,.right,.center]
    }
}

3. 原始值、隐式赋值

C或Objective-C中的枚举,是可以通过0 1 2 3...来初始化和使用。Swift枚举默认不会为每个成员分配0 1 2 3...也不能通过整数初始化枚举。要想获得这种特性,必须添加原始值。语法如下

enum TextAlignment:Int {}

原始值可以是字符串、字符或任何整数或浮点数类型。但是每个值对应的原始值必须是唯一的。

enum TextAlignment:String {
    case left = "0"
    case right = "1"
    case center = "2"
}

通过rawValue创建的枚举值是可选的?

var aligent = TextAlignment(rawValue:"1") 
// Optional(TextAlignment. right)

RawRepresentable协议

实现 RawRepresentable 协议的类型会获得两个新的 API:一个 rawValue 属性和一个可失败的初始化方法 (init?(rawValue:)),编译器自动为具有原始值的枚举实现这个协议。

编译器会通过递增前一个成员的原始值来给下一个枚举成员赋值。

enum TextAlignment:Int{
    case left
    case right
    case center
}
// 系统会自动分配 0 ,1,2给成员
var alignment : TextAlignment = .center 
alignment.rawValue // 2

原始值是String的时候,默认情况下系统用 case 值来初始化枚举原始值:

enum TextAlignment:String{
    case left
    case right
    case center
}
var alignment: TextAlignment = .left
print(alignment.rawValue) // "left"

4. 枚举关联值

原始值与关联值不同,枚举成员一旦设置了原始值使用中就不能在变,关联可以根据使用变化。

一个确定枚举值加上其关联值可以使的该枚举类型有更多的成员,Swift可以枚举成员关联任意类型的值

enum TextAlignment{
    case left(String)
    case right(String)
    case center(CGFloat,CGFloat)
}

5. 枚举支持范型&关联值

范型是Swift最强大的功能之一,Swift标准库的大部分都是用通用代码构建的。它能使您编写灵活、可重用的函数和类型,这些函数和类型可以根据您定义的要求适用于任何类型,避免重复的代码。

关于枚举的范型,看如下的例子:
定义范型枚举Result

// 定义范型枚举Result
enum Result{
    case success(Success)
    case failure(Failure)
}

使用Result

struct LError:Error{
    var message = "错误信息"
}
// 网络请求结果
var result:Result = .success(["code":"200"])
// 失败时 
result = .failed(LError(message: "404"))
//通过switch匹配结果
switch result{
case.success(let data):
    print(data)
case.failed(let error):
    let ler = error as! LError
    print(ler.message)
}

实际上,范型枚举都是和关联值结合使用的。Swift自带的Result类型也是这种形式的枚举。
假如我们要从本地磁盘读取文件,这个过程可能会失败,可以设定读取结果可选?这样以来,读取失败就会返回nil,但是我们不知道失败的原因,Result就可以表达那些需要提供详细信息的错误。如果我们不关注错误原因,直接忽略failed后面的关联值即可(下文有讲述如何忽略关联值)。

  1. 枚举使用就简单介绍到这里,接下来重点看枚举的使用和模式匹配。

Swift 要求枚举必须考虑到每一种情况,最常用方法就是使用 switch 语句

普通枚举,没有关联值的情况

var aligent:TextAlignment = .left
// 模式匹配 ,所有情况 left, right,center
switch aligent{
case .left:
    break
case .right:
    break
case .center:
    break
}

通配符 _ ,下划线匹配任意值并忽略这个值,等同default

// default 忽略
switch aligent {
case .left:
    break
default:
    break
}
// 通配符 _ 
switch aligent {
case .left:
    break
case _ :
    break
}

匹配多个值的情况,多个枚举值可以写在一行,也可以使用通配符_,default。

// 匹配多个的情况
switch aligent {
case .left,.right:
    break
case .center:
    break
}

除了switch之外,也可以用if 和if case 匹配

if aligent == .left{
  // do ...    
}

if case .left = aligent {
     // do ... 
}

值绑定模式,像处理可选值一样,可以把枚举的关联值绑定到一个let or var 声明的变量上,带关联值的枚举如下:

var aligent1:TextAlignment = .left("left")
var aligent2:TextAlignment = .center(0, 0)
// 值绑定模式
switch aligent1 {
case .left(let string): //绑定到变量 string 
    break
case .right(let string):
    break
case .center(let x, let y): //绑定到变量x,y 
    break
}
// let写在前面也是可以的
switch aligent1 {
case let.center(x, y):
    break
case let.right(str):
    break
case _:
    break
}

如果想忽略关联值,可以按照编译器提示用下划线_忽略,或者不写后面的括号()

// 用下划线_忽略
switch aligent1 {
case .left(_):
    break
case .right(_):
    break
case .center(_,_):
    break
}
// 不写后面的括号()
switch aligent1 {
case .left:
    break
case .right:
    break
case .center:
    break
}

关联值有单个or多个,匹配确定的关联值。

// 匹配确定的关联值  center(x,y)中的x=0,y=0的情况
switch aligent1 {
case .center(0,_):
    break
case _:
    break
}
// 只匹配确定的关联值  center(x,y)中的x=0的情况
switch aligent1 {
case .center(0,_):
    break
case _:
    break
}

你可能感兴趣的:(Swift枚举详解)