swift小知识点之枚举
一,枚举的基本用法
-
定义
定义方向的枚举enum Direction { case north case south case east case west }
上面也可以写成
enum Direction { case north, south, east, west }
-
使用
var dir = Direction.west dir = Direction.east dir = .north print(dir) // north
也可以在switch中使用
switch dir { case .north: print("north") case .south: print("south") case .east: print("east") case .west: print("west") }
也可以进行场景对比
if dir == .north { print("north") }
关联值
-
有时将枚举的成员值跟其他类型的值关联存储在一起,会非常有用,可以认为将值直接存入到枚举的内存中
enum Score { case points(Int) case grade(Character) }
如下使用:
var score = Score.points(88) score = .grade("A")
如果我们想使用枚举的具体值,可以如下用 i 来保存数据
switch score { case let .points(i): print(i, "points") case let .grade(i): print("grade", i) }
// grade A再比如我们想定义日期的枚举值,可以如下:
enum Date { case digit(year: Int, month: Int, day: Int) case string(String) }
//使用的时候,可以直接传年月日,或者传字符串var date = Date.digit(year: 2021, month: 9, day: 10) date = .string("2021-09-10")
switch date { case .digit(let year, let month, let day): rint(year, month, day) case let .string(value): print(value) }
-
必要时let也可以改为var
原始值
-
枚举成员可以使用相同类型的默认值预先关联,这个默认值叫做:原始值
定义枚举enum Grade : String { case perfect = "A" case great = "B" case good = "C" case bad = "D" }
使用print(Grade.perfect.rawValue) // A print(Grade.great.rawValue) // B print(Grade.good.rawValue) // C print(Grade.bad.rawValue) // D
-
注意:原始值不占用枚举变量的内存
隐式原始值(Implicitly Assigned Raw Values)
如果枚举的原始值类型是Int、String,CGfloat, Swift会自动分配原始值
-
原始值是 String 类型枚举值
定义枚举值enum Direction : String { case north = "north" case south = "south" case east = "east" case west = "west" }
等价于enum Direction : String { case north,south,east,west }
使用print(Direction.north) // north print(Direction.north.rawValue) // north
-
原始值是 Int 类型枚举值
定义enum Season : Int { case spring, summer, autumn, winter }
结果print(Season.spring.rawValue) // 0 print(Season.summer.rawValue) // 1 print(Season.autumn.rawValue) // 2 print(Season.winter.rawValue) // 3
如果自己指定了原始值
定义enum Season : Int { case spring = 1, summer, autumn = 8, winter }
结果
print(Season.spring.rawValue) // 1 print(Season.summer.rawValue) // 2 print(Season.autumn.rawValue) // 8 print(Season.winter.rawValue) // 9
从原始值初始化
如果你用原始值类型来定义一个枚举,那么枚举就会自动收到一个可以接受原始值类型的值的初始化器(叫做 rawValue的形式参数)然后返回一个枚举成员或者 nil 。你可以使用这个初始化器来尝试创建一个枚举的新实例。
这个例子从它的原始值 7来辨认出 uranus :
let possiblePlanet = Planet(rawValue: 7) // possiblePlanet is of type Planet? and equals Planet.Uranus
总之,不是所有可能的Int值都会对应一个行星。因此原始值的初始化器总是返回可选的枚举成员。在上面的例子中, possiblePlanet的类型是 Planet? ,或者“可选项 Planet”
注意
原始值初始化器是一个可失败初始化器,因为不是所有原始值都将返回一个枚举成员。
如果你尝试寻找有位置 11的行星,那么被原始值初始化器返回的可选项 Planet值将会是 nil:
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"
这个例子使用可选项绑定来尝试访问一个原始值是 11 的行星。其中的 if let somePlanet = Planet(rawValue: 11)语句创建了一个可选项 Planet,而且如果 Planet的值可被取回的话,就将它赋给 somePlanet。在这种情况下,取回一个位置为 11的行星是不可能的,所以执行 else分支会被执行。
遍历枚举情况(case)
对于某些枚举来说,如果能有一个集合包含了枚举的所有情况就好了。你可以通过在枚举名字后面写 : CaseIterable 来允许枚举被遍历。Swift 会暴露一个包含对应枚举类型所有情况的集合名为 allCases 。下面是例子:
enum Beverage: CaseIterable { case coffee, tea, juice } let numberOfChoices = Beverage.allCases.count print("\(numberOfChoices) beverages available") // Prints "3 beverages available"
在上面的例子中,你写了一个 Beverage.allCases 来访问包含 Beverage 枚举所有情况的集合。你可以把 allCases 当成和其他任意集合——集合的元素就是枚举类型的实例,所以在这里就是 Beverage 的值。上面的例子计数了有多少个情况,然后下面的例子使用 for 循环来遍历所有情况。
for beverage in Beverage.allCases { print(beverage) } // coffee // tea // juice
上面例子中使用的语法是标记枚举遵循 CaseIterable 协议
属性和方法
-
属性(只能是计算属性,其实也相当于方法)
增加一个存储属性到枚举中不被允许,但你依然能够创建计算属性。当然,计算属性的内容都是建立在枚举值下或者枚举关联值得到的。
enum Device { case iPad,iPhone var year:Int { switch self { case .iPhone: return 2007 case .iPad : return 2010 } }
- 方法
-
实例方法
很清晰,我们定义了一个设备枚举,有iPad, iPhone, AppleTV, AppleWatch,还有一个介绍的方法。这里的enum Device { case iPad, iPhone, AppleTV, AppleWatch func introduced() -> String { switch self { case .iPad: return "ipad" case .iPhone: return "iPhone" case .AppleTV:return "AppleWatch" case .AppleWatch:return "AppleTV" } } } print(Device.iPad.introduced())introduced方法,你可以认为枚举是一个类,introduced是一个成员方法,Device.iPhone就是一个Device的实例,case们是他的属性,好了,有了这个对像,Device.iPhone可以认为,Device里面有一个匿名属性,现在设置这个属性为iPhone。好了,introduced里面的switch self,其实就是遍历这个匿名属性的所有场景,如iPad,iPhone等,然后根据不同的场景返回不同的值。 -
静态方法
enum Device { case iPad,iPhone,AppleTV,AppleWatch ///1. 实例方法 func introduced() -> String { switch self { case .iPad: return "iPad" case .iPhone:return "iPhone" case .AppleTV:return "AppleWatch" case .AppleWatch:return "AppleTV" } } ///2. 静态方法 static func fromSlang(term:String) -> Device? { if term == "iWatch" { return .AppleWatch } return nil } } print(Device.fromSlang(term: "iWatch")!)
-
协议
Swift也允许你在枚举中使用协议(Protocols)和协议扩展(Protocol Extension)。
Swift协议定义一个接口或类型以供其他数据结构来遵循。enum当然也不例外。我们先从Swift标准库中的一个例子开始.
CustomStringConvertible是一个以打印为目的的自定义格式化输出的类型。
protocol CustomStringConvertible { var description:String{get} }
该协议只有一个要求,即一个只读(getter)类型的字符串(String类型)。我们可以很容易为enum实现这个协议。
///协议 protocol CustomStringConvertible { var description:String{get} } ///定义枚举 enum Trade:CustomStringConvertible { case Buy(stock:String, amount:Int) case Sell(stock:String,amount:Int) var description: String { switch self { case .Buy(stock:_ ,amount:_): return "Buy" case .Sell(stock:_ ,amount:_): return "Sell" } } } ///打印 print(Trade.Buy(stock: "003100", amount: 100).description)
扩展
枚举也可以进行扩展。最明显的用例就是将枚举的case和method分离,这样阅读你的代码能够简单快速地消化掉enum内容,紧接着转移到方法定义:
///1.协议 protocol CustomStringConvertible { var description:String{get} } ///2.定义枚举 enum Device { case iPad,iPhone,AppleTV,AppleWatch } ///3.拓展枚举&遵守协议 extension Device:CustomStringConvertible { func introduced() -> String { switch self { case .iPad: return "ipad" case .iPhone: return "iPhone" case .AppleTV: return "AppleTV" case .AppleWatch: return "AppleWatch" } } var description: String { switch self { case .iPad: return "ipad" case .iPhone: return "iPhone" case .AppleWatch: return "AppleWatch" case .AppleTV: return "AppleTV" } } } print(Device.AppleTV.description) print(Device.AppleTV.introduced())
泛型
///1.泛型枚举定义 enum Rubblish<T> { case price(T) func getPrice() -> T { switch self { case .price(let value): return value } } } ///2.打印 print(Rubblish<Int>.price(100).getPrice())
浙公网安备 33010602011771号