Swift 枚举(enum)详解

Swift基础语法总结,来自苹果官方文档

枚举(Enumeration)

枚举在Swift中是 first-class types。与C,Objective-C中的枚举相比,Swift中枚举功能更强大。它支持很多只有类才有的特性,如: PropertiesMethodsInitializationExtensionsProtocols.

1. 语法格式

enum 枚举名{
    case
    case
    case
    ...
}

举例:

//多个case分开写
enum CompassPoint {
    case north
    case south
    case east
    case west
}

//多个case写在同一行,使用逗号分开
enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}

//创建CompassPoint的枚举实例
var directionToHead = CompassPoint.west
directionToHead = .east

注意:与C和Objective-C不同,Swift枚举情况在创建时不分配默认整数值。在CompassPoint例子中,north,south,east和west不等于隐式0,1,2和3。

2. Switch和Enumeration

通常将单个枚举值与switch语句匹配:

//switch覆盖CompassPoint的所有情况
directionToHead = .south
switch directionToHead {
case .north:
    print("Lots of planets have a north")
case .south:
    print("Watch out for penguins")
case .east:
    print("Where the sun rises")
case .west:
    print("Where the skies are blue")
}
// Prints "Watch out for penguins"


//switch 没有覆盖Planet的所有情况,需要添加default
let somePlanet = Planet.earth
switch somePlanet {
case .earth:
    print("Mostly harmless")
default:
    print("Not a safe place for humans")
}
// Prints "Mostly harmless"

注意:当switch没有覆盖枚举中所有case时,需要添加default,来处理其他情况!

3.迭代枚举

当需要迭代枚举中的所有情况时,需要自定义的枚举遵守CaseIterable协议

enum Beverage: CaseIterable {
    case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
// Prints "3 beverages available"


for beverage in Beverage.allCases {
    print(beverage)
}
// coffee
// tea
// juice

4.关联值(Associated Values)

我们可以定义Swift枚举来存储任何给定类型的关联值,而且每种枚举情况的值类型可以不同。

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

//创建Barcode枚举实例
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

可以将关联值提取为switch语句的一部分。将每个关联值提取为常量(let)或变量(var),以便在switch中处理:

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
    print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."

如果枚举case的所有关联值都被提取为常量,或者都被提取为变量,则可以将var或let放置在case名称前面,来提取所有的关联值:

switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
    print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
    print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."

5.原始值(Raw Values)

关联值 ”表明了枚举如何存储不同类型的关联值。作为关联值的替代,枚举情况可以预先设置默认值(称原始值),它们都是相同的类型。
原始值可以是字符串,字符,整数或浮点数类型。每个原始值在其枚举声明中必须是唯一的。

enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

注意:原始值是不一样的关联值。当您首次在代码中定义枚举时,原始值将设置为预填充值,如上面的三个ASCII代码。特定枚举情况的原始值始终相同。根据枚举的情况创建新常量或变量时,将设置关联值,每次执行此操作时可能会有所不同。

(1). 隐式分配原始值

当使用存储整数或字符串原始值的枚举时,不必为每种case显式分配原始值,Swift将自动为其分配值。如果使用整数为原始值,则每个case的原始值依次自增1。若第一个case没有设置原始值,则默认为0:

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

当使用字符串作为原始值时,每个case的隐含值是该case的名称。

enum CompassPoint: String {
    case north, south, east, west
}

使用枚举的rawValue属性来访问其原始值:

let earthsOrder = Planet.earth.rawValue
// earthsOrder is 3

let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"
(2).使用原始值初始化枚举实例

如果使用原始值类型定义枚举,则枚举会自动接收一个带有原始值的初始化器,并返回可选类型的枚举实例。

let possiblePlanet = Planet(rawValue: 7)

let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
    switch somePlanet {
    case .earth:
        print("Mostly harmless")
    default:
        print("Not a safe place for humans")
    }
} else {
    print("There isn't a planet at position \(positionToFind)")
}
// Prints "There isn't a planet at position 11"

注意:原始值初始化器是一个可用的初始化器,因为并非每个原始值都将返回枚举情况。Failable Initializers

6.递归枚举

递归枚举是将枚举的另一个实例作为一个或多个枚举case的关联值。在枚举case 前面添加关键字indirect来指明该枚举case是递归的,这就告诉了编译器插入必要的间接层。
例如,下面是存储简单算术表达式的枚举:

enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}

还可以在枚举enum之前添加indirect,以便为所有具有关联值的枚举case启用间接:

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

递归函数是处理具有递归结构的数据的简单方法。例如,这是一个计算算术表达式的函数:

func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}

print(evaluate(product))
// Prints "18"

7.其他专题模块

Swift 4.2 基础专题详解

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

推荐阅读更多精彩内容