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<Success, Failure>{
    case success(Success)
    case failure(Failure)
}

使用Result

struct LError:Error{
    var message = "错误信息"
}
// 网络请求结果
var result:Result<Dictionary, LError > = .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
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容