array高级用法 swift
2018-04-25 14:29:00 weixin_33720078 阅读数 29
``````import UIKit

//数组问题

struct student {

var name ="123"

}

var str ="Hello, playground"

//将多个数组合成一个数组

let array = [[1,2,4,],[3,5],[565,33]]

//let arrayMap = array.map{\$0}

let arrayFlat = [[123,123],[444]].flatMap{ \$0 }

print(arrayFlat)

//分离出条件内的数字并和成数组

let arrayFilter = [1,2,3,4,5,6,20]

let tempFilter = arrayFilter.filter{ \$0 % 2 == 0 }

print(tempFilter)

//获取数组的和

let sumArray = [2,3,5,6,7]

let tempSum = sumArray.reduce(0){ \$0 + \$1}

print(tempSum)

//从类里面遍历出来

var oneS = student.init()

oneS.name = "1"

var oneS1 = student.init()

oneS1.name = "2"

var oneS2 = student.init()

oneS2.name = "3"

let students = [oneS,oneS1,oneS2]

let endS = students.filter { (student) -> Bool in

return student.name == "2"

}

if let endA = endS.last {

print(endS.last)

}

//取出空数组

let nilArray = [[],[23,322],[4,3,4],[],[666,777],[]]

let tempNilArray = nilArray.filter { (array) -> Bool in

return array.count > 0

}

print(tempNilArray)

//forEach遍历数据

let testArrA = [1,4,5,6,1]

let testArrB = [1,2,3,4,5]

let testArrC = ["a","b","c","D"]

(2..

print(countT)

}

//遍历

testArrC.enumerated().forEach { (oneStr) in

print(oneStr.element)

}

//从某一点这个点开是，分离成两个数组，并去掉当前的元素

testArrA.split(separator: 4)

testArrC.split(separator: "b")

//条件分离

testArrA.split { (tempInt) -> Bool in

return tempInt <= 1

}

//删除索引之前的对象

testArrC.dropFirst(0)

testArrC.dropLast(1)

//修改数组元素内容

print(testArrC.map{\$0.lowercased()})

//排序

print(testArrC.sorted(by: < ))

print(testArrB.sorted(by: < ))

//倒序

print(Array(testArrA.reversed()))

//prefix,取前几位的值

print(testArrA.prefix(3))

//suffix，取后几位的值

print(testArrA.suffix(1))

// 运算符重载

func == (stu1: student,stu2: student) -> Bool {

if stu1.name == stu2.name {

return true

}

return false

}

let isEqual = oneS1 == oneS

let threeArr = [1] + [3] + [1,0,88]

let befor =1

let later = ~1

print(later)

//枚举

enum WeekType {

case One

case Two

}  ``````

array高级用法 swift 相关内容

2017-02-06 14:17:54 Arodung 阅读数 1874

```//: Playground - noun: a place where people can play

import UIKit

//数组问题
struct student {
var name = "123"

}

var str = "Hello, playground"

//将多个数组合成一个数组
let array = [[1,2,4,],[3,5],[565,33]]
//let arrayMap = array.map{\$0}
let arrayFlat = [[123,123],[444]].flatMap{ \$0 }
print(arrayFlat)

//分离出条件内的数字并和成数组
let arrayFilter = [1,2,3,4,5,6,20]
let tempFilter = arrayFilter.filter{ \$0 % 2 == 0 }
print(tempFilter)

//获取数组的和
let sumArray = [2,3,5,6,7]
let tempSum = sumArray.reduce(0){ \$0 + \$1}
print(tempSum)

//从类里面遍历出来
var oneS = student.init()
oneS.name = "1"
var oneS1 = student.init()
oneS1.name = "2"
var oneS2 = student.init()
oneS2.name = "3"
let students = [oneS,oneS1,oneS2]
let endS = students.filter { (student) -> Bool in
return student.name == "2"
}
if let endA = endS.last {
print(endS.last)
}

//取出空数组
let nilArray = [[],[23,322],[4,3,4],[],[666,777],[]]
let tempNilArray = nilArray.filter { (array) -> Bool in
return array.count > 0
}
print(tempNilArray)

//forEach遍历数据
let testArrA = [1,4,5,6,1]
let testArrB = [1,2,3,4,5]
let testArrC = ["a","b","c","D"]
(2..<testArrA.count).forEach { (countT) in
print(countT)
}

//遍历
testArrC.enumerated().forEach { (oneStr) in
print(oneStr.element)
}

//从某一点这个点开是，分离成两个数组，并去掉当前的元素
testArrA.split(separator: 4)
testArrC.split(separator: "b")
//条件分离
testArrA.split { (tempInt) -> Bool in
return tempInt <= 1
}

//删除索引之前的对象
testArrC.dropFirst(0)
testArrC.dropLast(1)

//修改数组元素内容
print(testArrC.map{\$0.lowercased()})

//排序
print(testArrC.sorted(by: < ))
print(testArrB.sorted(by: < ))

//倒序
print(Array(testArrA.reversed()))

//prefix,取前几位的值
print(testArrA.prefix(3))

//suffix，取后几位的值
print(testArrA.suffix(1))

// 运算符重载
func == (stu1: student,stu2: student) -> Bool {
if stu1.name == stu2.name {
return true
}
return false
}

let isEqual = oneS1 == oneS
let threeArr = [1] + [3] + [1,0,88]

let befor = 1
let later = ~1
print(later)

//枚举
enum WeekType {
case One
case Two
}```

array高级用法 swift 相关内容

2016-03-07 21:47:35 qq_32780047 阅读数 353
``````// 高级用法 (面试)
// 可选类型 值绑定(可选类型结合 if-else 使用), 都要定义局部变量
var bindingOptional:Int!
// local生命周期 - if 结束
// * 局部变量后面必须是可选类型, 其实判断的是可选类型是否为空, 当为空时,直接走 else, 都有值时,走 if,顺便完成局部变量的赋值,方便我们在 if 花括号中对局部变量的使用
if var local = bindingOptional {
print("local = \(local)")
} else {
print("值为空")
}

// switch - case
// 1.switch 中, 功能更强大
// 2.默认没有贯穿, fallthrough关键词为贯穿下面的内容, 就是在得到要的值后面还会输出下面的内容

var switchNumber = 5
// case 一定包含所有的情况, 如果情况不能都写完, 就用 default 代替
switch switchNumber {
case 0,1,2,3,4:
print("小于5")
fallthrough
case 6...100:
print("大于5小于100")
fallthrough
case 5:
print("5")
fallthrough
default:
print("others")
}

// 高级用法(面试)
// switch - case 值绑定
// 把一个作为判断条件, 一个作为局部变量接受值
// 利用系统的推断
var (x,y) = (10, 0)
switch (x,y) {
case (var xValue, 0):
print("xValue = \(xValue)")
case (0,var yValue):
print("yValue = \(yValue)")
default:
print("位于坐标系内")
}

// 循环
for var i = 0; i < 10; i++ {
print("i = \(i)")
}

// for - in循环
for i in 1...10 {
print("i = \(i)")
}

// while 循环
var whileNumber = 0
while whileNumber < 10 {
print("whileNumber = \(whileNumber)")
whileNumber++
}

// repeat - while 循环
// 先执行, 后判断
repeat {
print("我能行")
} while false

// 标签语句
// 应用场景: 循环嵌套
// 准确的取消哪一个循环, 想取消哪一个循环, 就该哪一个循环取个标签
joner: while true {
for var i = 0; i < 50; i++ {
print("i == \(i)")
if i == 5 {
break joner
}
}
}

// 枚举
// 还是值类型
enum Person {
case Shaoqiong
case Xiaoze
case Bowen
}

print(Person.Bowen.hashValue)

// ***开发中
// 原始值
// 指定枚举值的类型 Int
enum Fruit:Int {
case Apple
case Banana
case Orange
}
// 原始值, rawValue 就是原始值
print(Fruit.Orange.rawValue)

// 函数, 是一个引用类型
// 函数其实就是OC当中的方法

// 定义函数使用 func
// 1.没返回值, 没参数
// 注意:()里卖写的是参数列表, ->代表返回值
// 函数的类型包括参数类型和返回值类型
// eg.()->Void 整体是一个类型
// 书写时:->Void 可以省
func printStr()->Void {
print("hello world")
}
// 函数调用
printStr()

// 2.没返回值, 有参数
// (String)->Void为函数类型
func printPersonName(name:String) {
print("name = \(name)")
}
// 调用
printPersonName("gangyun")
// *常量
var jonerFunc :(String)->Void = printPersonName
// 调用 jonerFunc
jonerFunc("qiong")
// *多个参数
func printPersonInfo(name:String,age:Int) {
print("name = \(name), age = \(age)")
}
printPersonInfo("joner", age: 23)

// 3.有返回值, 无参数

// 4.有返回值, 有参数
// 函数类型 (String)->String
func returnPersonName(name:String) ->String {
return name
}
var returnName =  returnPersonName("joner")
print("returnName = \(returnName)")

// 多个参数多个返回值, 借助元祖
// (String,Int,Float)->(String,Int,Float)为函数类型
func returnPersonInfo(name:String,age:Int, height:Float) ->(String,Int,Float) {
return (name,age, height)
}
// 接受:
var (name,shaoqiongAge,height) =  returnPersonInfo("shaoqiong", age: 19, height: 160.0)
print("name = \(name),shaoqiongAge = \(shaoqiongAge),height = \(height)")

// *使用函数的注意事项
// 1.参数在默认情况下是 let 类型, 是不能改变的,想改变的话,参数必须使用 var 修饰
func changeBottleHeight(var height:Float) {
// 高度的改变
height += 49
}
// 2.
// 封装交换两个值得函数, 想改变-用地址(加&, 关键字- inout), 因为其为值传递
//当想要函数的交换, 影响外部值的时候, 变量的关键字-形参的关键字用 inout(输入输出关键字)
func swapTwoNumber( inout a:Int, inout b:Int) {
// let tmp:Int = a;
var tmp:Int = 0
tmp = a
a = b
b = tmp
}
var aa = 49,bb = 94
swapTwoNumber(&aa, b: &bb)
print("aa = \(aa),bb = \(bb)")``````

array高级用法 swift 相关内容

2018-01-12 19:43:00 weixin_33672109 阅读数 20

# defer 修饰符

1. defer ： 在当前作用域执行完后再执行defer中的代码
get方法中执行顺序为：
1.`lock.lock()`
2.`return requests[task.taskIdentifier]`
3.`defer { lock.unlock() }`
``````//摘自alamofier -> sessionDelegate.swift (第170-179行)
get {
lock.lock() ; defer { lock.unlock() }
}
set {
lock.lock() ; defer { lock.unlock() }
}
}
``````

# 奇怪的函数

## <-

`摘自ObjectMapper ->EnumOperators.swift`

``````/// Object of Raw Representable type
public func <- <T: RawRepresentable>(left: inout T, right: Map) {
left <- (right, EnumTransform())
}
``````
``````public func >>> <T: RawRepresentable>(left: T, right: Map) {
left >>> (right, EnumTransform())
}

/// Optional Object of Raw Representable type
public func <- <T: RawRepresentable>(left: inout T?, right: Map) {
left <- (right, EnumTransform())
}

public func >>> <T: RawRepresentable>(left: T?, right: Map) {
left >>> (right, EnumTransform())
}

/// Implicitly Unwrapped Optional Object of Raw Representable type
public func <- <T: RawRepresentable>(left: inout T!, right: Map) {
left <- (right, EnumTransform())
}

// MARK:- Arrays of Raw Representable type

/// Array of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [T], right: Map) {
left <- (right, EnumTransform())
}

public func >>> <T: RawRepresentable>(left: [T], right: Map) {
left >>> (right, EnumTransform())
}

/// Array of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [T]?, right: Map) {
left <- (right, EnumTransform())
}

public func >>> <T: RawRepresentable>(left: [T]?, right: Map) {
left >>> (right, EnumTransform())
}

/// Array of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [T]!, right: Map) {
left <- (right, EnumTransform())
}

// MARK:- Dictionaries of Raw Representable type

/// Dictionary of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [String: T], right: Map) {
left <- (right, EnumTransform())
}

public func >>> <T: RawRepresentable>(left: [String: T], right: Map) {
left >>> (right, EnumTransform())
}

/// Dictionary of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [String: T]?, right: Map) {
left <- (right, EnumTransform())
}

public func >>> <T: RawRepresentable>(left: [String: T]?, right: Map) {
left >>> (right, EnumTransform())
}

/// Dictionary of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [String: T]!, right: Map) {
left <- (right, EnumTransform())
}
``````

## []

`摘自Map.swift`

``````/// Sets the current mapper value and key.
/// The Key paramater can be a period separated string (ex. "distance.value") to access sub objects.
public subscript(key: String) -> Map {
// save key and value associated to it
return self[key, delimiter: ".", ignoreNil: false]
}

public subscript(key: String, delimiter delimiter: String) -> Map {
let nested = key.contains(delimiter)
return self[key, nested: nested, delimiter: delimiter, ignoreNil: false]
}

public subscript(key: String, nested nested: Bool) -> Map {
return self[key, nested: nested, delimiter: ".", ignoreNil: false]
}

public subscript(key: String, nested nested: Bool, delimiter delimiter: String) -> Map {
return self[key, nested: nested, delimiter: delimiter, ignoreNil: false]
}

public subscript(key: String, ignoreNil ignoreNil: Bool) -> Map {
return self[key, delimiter: ".", ignoreNil: ignoreNil]
}

public subscript(key: String, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map {
let nested = key.contains(delimiter)
return self[key, nested: nested, delimiter: delimiter, ignoreNil: ignoreNil]
}

public subscript(key: String, nested nested: Bool, ignoreNil ignoreNil: Bool) -> Map {
return self[key, nested: nested, delimiter: ".", ignoreNil: ignoreNil]
}

public subscript(key: String, nested nested: Bool, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map {
// save key and value associated to it
currentKey = key
keyIsNested = nested
nestedKeyDelimiter = delimiter

if mappingType == .fromJSON {
// check if a value exists for the current key
// do this pre-check for performance reasons
if nested == false {
let object = JSON[key]
let isNSNull = object is NSNull
isKeyPresent = isNSNull ? true : object != nil
currentValue = isNSNull ? nil : object
} else {
// break down the components of the key that are separated by .
(isKeyPresent, currentValue) = valueFor(ArraySlice(key.components(separatedBy: delimiter)), dictionary: JSON)
}

// update isKeyPresent if ignoreNil is true
if ignoreNil && currentValue == nil {
isKeyPresent = false
}
}

return self
}
``````

## \$0

``````let numbers = [1,2,5,4,3,6,8,7]
sortNumbers = numbers.sorted(by: { (a, b) -> Bool in
return a < b
})
print("numbers -" + "\(sortNumbers)")
``````

``````let numbers = [1,2,5,4,3,6,8,7]
var sortNumbers = numbers.sorted(by: {\$0 < \$1})
print("numbers -" + "\(sortNumbers)")
``````

# 高阶函数

## map

``````// 计算字符串的长度
let stringArray = ["Objective-C", "Swift", "HTML", "CSS", "JavaScript"]
func stringCount(string: String) -> Int {
return string.characters.count
}
stringArray.map(stringCount)

stringArray.map({string -> Int in
return string.characters.count
})

// \$0代表数组中的每一个元素
stringArray.map{
return \$0.characters.count
}
``````

## flatMap

1. flatMap返回后的数组中不存在nil，同时它会把Optional解包

``````let array = ["Apple", "Orange", "Puple", ""]

let arr1 = array.map { a -> Int? in
let length = a.characters.count
guard length > 0 else { return nil }
return length
}
arr1 // [{some 5}, {some 6}, {some 5}, nil]

let arr2 = array.flatMap { a-> Int? in
let length = a.characters.count
guard length > 0 else { return nil}
return length
}
arr2 // [5, 6, 5]
``````

2. flatMap还能把数组中存有数组的数组（二维数组、N维数组）一同打开变成一个新的数组

``````let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

let arr1 = array.map{ \$0 }
arr1 // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

let arr2 = array.flatMap{ \$0 }
arr2 // [1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

3. flatMap也能把两个不同的数组合并成一个数组，这个合并的数组元素个数是前面两个数组元素个数的乘积

``````let fruits = ["Apple", "Orange", "Puple"]
let counts = [2, 3, 5]

let array = counts.flatMap { count in
fruits.map ({ fruit in
return fruit + "  \(count)"
})
}
array // ["Apple 2", "Orange 2", "Puple 2", "Apple 3", "Orange 3", "Puple 3", "Apple 5", "Orange 5", "Puple 5"]
``````

## filer

``````// 筛选出字符串的长度小于10的字符串
let stringArray = ["Objective-C", "Swift", "HTML", "CSS", "JavaScript"]
func stringCountLess10(string: String) -> Bool {
return string.characters.count < 10
}
stringArray.filter(stringCountLess10)

stringArray.filter({string -> Bool in
return string.characters.count < 10
})

// \$0表示数组中的每一个元素
stringArray.filter{
return \$0.characters.count < 10
}
``````

## reduce

``````// 将数组中的每个字符串用‘、’拼接
let stringArray = ["Objective-C", "Swift", "HTML", "CSS", "JavaScript"]

func appendString(string1: String, string2: String) -> String {
return string1 == "" ? string2 : string1 + "、" + string2
}
// reduce方法中的第一个参数是初始值
stringArray.reduce("", appendString)

stringArray.reduce("", {(string1, string2) -> String in
return string1 == "" ? string2 : string1 + "、" + string2
})

// \$0表示计算后的结果, \$1表示数组中的每一个元素
stringArray.reduce("", {
return \$0 == "" ? \$1 : \$0 + "、" + \$1
``````

# 参考资料

array高级用法 swift 相关内容

2017-08-31 16:40:00 itchosen 阅读数 12159

switch语句类似，`Swift`中的枚举乍看之下更像是`C`语言中枚举的进阶版本，即允许你定义一种类型，用于表示普通事情中某种用例。不过深入挖掘之后，凭借`Swift`背后特别的设计理念，相比较`C`语言枚举来说其在实际场景中的应用更为广泛。特别是作为强大的工具，`Swift`中的枚举能够清晰表达代码的意图。

## 深入理解(Diving In)

### 定义基本的枚举类型(Defining Basic Enums)

``````enum Movement{
case Left
case Right
case Top
case Bottom
}``````

``````let aMovement = Movement.Left

// switch 分情况处理
switch aMovement{
case .Left: print("left")
default:()
}

// 明确的case情况
if case .Left = aMovement{
print("left")
}

if aMovement == .Left { print("left") }``````

### 枚举值(Enum Values)

``````// 映射到整型
enum Movement: Int {
case Left = 0
case Right = 1
case Top = 2
case Bottom = 3
}

// 同样你可以与字符串一一对应
enum House: String {
case Baratheon = "Ours is the Fury"
case Greyjoy = "We Do Not Sow"
case Martell = "Unbowed, Unbent, Unbroken"
case Stark = "Winter is Coming"
case Tully = "Family, Duty, Honor"
case Tyrell = "Growing Strong"
}

// 或者float double都可以(同时注意枚举中的花式unicode)
enum Constants: Double {
case π = 3.14159
case e = 2.71828
case φ = 1.61803398874
case λ = 1.30357
}``````

``````// Mercury = 1, Venus = 2, ... Neptune = 8
enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

// North = "North", ... West = "West"
// 译者注: 这个是swift2.0新增语法
enum CompassPoint: String {
case North, South, East, West
}``````

`Swift`枚举中支持以下四种关联值类型:

• 整型(Integer)
• 浮点数(Float Point)
• 字符串(String)
• 布尔类型(Boolean)

``````let bestHouse = House.Stark
print(bestHouse.rawValue)
// prints "Winter is coming"``````

``````enum Movement: Int {
case Left = 0
case Right = 1
case Top = 2
case Bottom = 3
}
// 创建一个movement.Right 用例,其raw value值为1
let rightMovement = Movement(rawValue: 1)``````

``````enum VNodeFlags : UInt32 {
case Delete = 0x00000001
case Write = 0x00000002
case Extended = 0x00000004
case Attrib = 0x00000008
case Rename = 0x00000020
case Revoke = 0x00000040
case None = 0x00000080
}``````

### 嵌套枚举(Nesting Enums)

``````enum Character {
enum Weapon {
case Bow
case Sword
case Lance
case Dagger
}
enum Helmet {
case Wooden
case Iron
case Diamond
}
case Thief
case Warrior
case Knight
}``````

``````let character = Character.Thief
let weapon = Character.Weapon.Bow
let helmet = Character.Helmet.Iron``````

### 包含枚举(Containing Enums)

``````struct Character {
enum CharacterType {
case Thief
case Warrior
case Knight
}
enum Weapon {
case Bow
case Sword
case Lance
case Dagger
}
let type: CharacterType
let weapon: Weapon
}

let warrior = Character(type: .Warrior, weapon: .Sword)``````

### 关联值(Associated Value)

``````enum Trade {
case Sell
}

``````enum Trade {
case Sell(stock: String, amount: Int)
}

``````let trade = Trade.Buy(stock: "APPL", amount: 500)
}``````

``````enum Trade {
case Sell(String, Int)
}``````

(元组参数)Tuple as Arguments

``````let tp = (stock: "TSLA", amount: 100)

}
// Prints: "buy 100 of TSLA"``````

``````typealias Config = (RAM: Int, CPU: String, GPU: String)

// Each of these takes a config and returns an updated config
func selectRAM(_ config: Config) -> Config {return (RAM: 32, CPU: config.CPU, GPU: config.GPU)}
func selectCPU(_ config: Config) -> Config {return (RAM: config.RAM, CPU: "3.2GHZ", GPU: config.GPU)}
func selectGPU(_ config: Config) -> Config {return (RAM: config.RAM, CPU: "3.2GHZ", GPU: "NVidia")}

enum Desktop {
case Cube(Config)
case Tower(Config)
case Rack(Config)
}

let aTower = Desktop.Tower(selectGPU(selectCPU(selectRAM((0, "", "") as Config))))``````

``````infix operator <^> { associativity left }

func <^>(a: Config, f: (Config) -> Config) -> Config {
return f(a)
}``````

``````let config = (0, "", "") <^> selectRAM  <^> selectCPU <^> selectGPU
let aCube = Desktop.Cube(config)``````

``````// 拥有不同值的用例
enum UserAction {
case OpenURL(url: NSURL)
case SwitchProcess(processId: UInt32)
case Restart(time: NSDate?, intoCommandLine: Bool)
}

// 假设你在实现一个功能强大的编辑器，这个编辑器允许多重选择，
// 正如 Sublime Text : https://www.youtube.com/watch?v=i2SVJa2EGIw
enum Selection {
case None
case Single(Range<Int>)
case Multiple([Range<Int>])
}

// 或者映射不同的标识码
enum Barcode {
case UPCA(numberSystem: Int, manufacturer: Int, product: Int, check: Int)
case QRCode(productCode: String)
}

// 又或者假设你在封装一个 C 语言库，正如 Kqeue BSD/Darwin 通知系统:
// https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
enum KqueueEvent {
case UserEvent(identifier: UInt, fflags: [UInt32], data: Int)
case WriteFD(fd: UInt, data: Int)
case VnodeFD(fd: UInt, fflags: [UInt32], data: Int)
case ErrorEvent(code: UInt, message: String)
}

// 最后, 一个 RPG 游戏中的所有可穿戴装备可以使用一个枚举来进行映射，
// 可以为一个装备增加重量和持久两个属性
// 现在可以仅用一行代码来增加一个"钻石"属性，如此一来我们便可以增加几件新的镶嵌钻石的可穿戴装备
enum Wearable {
enum Weight: Int {
case Light = 1
case Mid = 4
case Heavy = 10
}
enum Armor: Int {
case Light = 2
case Strong = 8
case Heavy = 20
}
case Helmet(weight: Weight, armor: Armor)
case Breastplate(weight: Weight, armor: Armor)
case Shield(weight: Weight, armor: Armor)
}
let woodenHelmet = Wearable.Helmet(weight: .Light, armor: .Light)``````

### 方法和属性(Methods and properties)

``````enum Wearable {
enum Weight: Int {
case Light = 1
}
enum Armor: Int {
case Light = 2
}
case Helmet(weight: Weight, armor: Armor)
func attributes() -> (weight: Int, armor: Int) {
switch self {
case .Helmet(let w, let a): return (weight: w.rawValue * 2, armor: w.rawValue * 4)
}
}
}
let woodenHelmetProps = Wearable.Helmet(weight: .Light, armor: .Light).attributes()
print (woodenHelmetProps)
// prints "(2, 4)"``````

``````enum Device {
func introduced() -> String {
switch self {
case AppleTV: return "\(self) was introduced 2006"
case iPhone: return "\(self) was introduced 2007"
case iPad: return "\(self) was introduced 2010"
case AppleWatch: return "\(self) was introduced 2014"
}
}
}
print (Device.iPhone.introduced())
// prints: "iPhone was introduced 2007"``````

``````enum Device {
var year: Int {
switch self {
case iPhone: return 2007
}
}
}``````

``````enum Device {
case AppleWatch
static func fromSlang(term: String) -> Device? {
if term == "iWatch" {
return .AppleWatch
}
return nil
}
}
print (Device.fromSlang("iWatch"))``````

``````enum TriStateSwitch {
case Off, Low, High
mutating func next() {
switch self {
case Off:
self = Low
case Low:
self = High
case High:
self = Off
}
}
}
var ovenLight = TriStateSwitch.Low
ovenLight.next()
// ovenLight 现在等于.On
ovenLight.next()
// ovenLight 现在等于.Off``````

### 小结(To Recap)

``````// Struct Example
struct Point { let x: Int, let y: Int }
struct Rect { let x: Int, let y: Int, let width: Int, let height: Int }

// Enum Example
enum GeometricEntity {
case Point(x: Int, y: Int)
case Rect(x: Int, y: Int, width: Int, height: Int)
}``````

``````// C-Like example
case Sell
}

// Swift Enum example
case Sell
func order()
}``````

### 协议(Protocols)

`Swift`协议定义一个接口或类型以供其他数据结构来遵循。`enum`当然也不例外。我们先从`Swift`标准库中的一个例子开始.

`CustomStringConvertible`是一个以打印为目的的自定义格式化输出的类型。

``````protocol CustomStringConvertible {
var description: String { get }
}``````

``````enum Trade: CustomStringConvertible {
var description: String {
switch self {
case Sell: return "We're selling something"
}
}
}

print("this action is \(action)")
// prints: this action is We're buying something``````

``````protocol AccountCompatible {
var remainingFunds: Int { get }
mutating func removeFunds(amount: Int) throws
}``````

``````enum Account {
case Empty
case Funds(remaining: Int)

enum Error: ErrorType {
case Overdraft(amount: Int)
}

var remainingFunds: Int {
switch self {
case Empty: return 0
case Funds(let remaining): return remaining
}
}
}``````

``````extension Account: AccountCompatible {

mutating func addFunds(amount: Int) throws {
var newAmount = amount
if case let .Funds(remaining) = self {
newAmount += remaining
}
if newAmount < 0 {
throw Error.Overdraft(amount: -newAmount)
} else if newAmount == 0 {
self = .Empty
} else {
self = .Funds(remaining: newAmount)
}
}

mutating func removeFunds(amount: Int) throws {
}

}
var account = Account.Funds(remaining: 20)
print ("remove 1: ", try? account.removeFunds(15))
print ("remove 2: ", try? account.removeFunds(55))
// prints:
// : remove 1:  Optional(())
// : remove 2:  nil``````

### 扩展(Extensions)

``````enum Entities {
case Soldier(x: Int, y: Int)
case Tank(x: Int, y: Int)
case Player(x: Int, y: Int)
}``````

``````extension Entities {
mutating func move(dist: CGVector) {}
mutating func attack() {}
}``````

``````extension Entities: CustomStringConvertible {
var description: String {
switch self {
case let .Soldier(x, y): return "\(x), \(y)"
case let .Tank(x, y): return "\(x), \(y)"
case let .Player(x, y): return "\(x), \(y)"
}
}
}``````

### 枚举泛型(Generic Enums)

``````let aValue = Optional<Int>.Some(5)
let noValue = Optional<Int>.None
if noValue == Optional.None { print("No value") }``````

``````// Simplified implementation of Swift's Optional
enum MyOptional<T> {
case Some(T)
case None
}``````

``````// The well-known either type is, of course, an enum that allows you to return either
// value one (say, a successful value) or value two (say an error) from a function
enum Either<T1, T2> {
case Left(T1)
case Right(T2)
}``````

``````// Totally nonsensical example. A bag that is either full (has an array with contents)
// or empty.
enum Bag<T: SequenceType where T.Generator.Element==Equatable> {
case Empty
case Full(contents: T)
}``````

### 递归 / 间接(Indirect)类型

``````enum FileNode {
case File(name: String)
indirect case Folder(name: String, files: [FileNode])
}``````

``````indirect enum Tree<Element: Comparable> {
case Empty
case Node(Tree<Element>,Element,Tree<Element>)
}``````

### 使用自定义类型作为枚举的值

``````enum Devices: CGSize {
case iPhone3GS = CGSize(width: 320, height: 480)
case iPhone5 = CGSize(width: 320, height: 568)
case iPhone6 = CGSize(width: 375, height: 667)
case iPhone6Plus = CGSize(width: 414, height: 736)
}``````

``````extension CGSize: StringLiteralConvertible {
public init(stringLiteral value: String) {
let size = CGSizeFromString(value)
self.init(width: size.width, height: size.height)
}

public init(extendedGraphemeClusterLiteral value: String) {
let size = CGSizeFromString(value)
self.init(width: size.width, height: size.height)
}

public init(unicodeScalarLiteral value: String) {
let size = CGSizeFromString(value)
self.init(width: size.width, height: size.height)
}
}``````

``````enum Devices: CGSize {
case iPhone3GS = "{320, 480}"
case iPhone5 = "{320, 568}"
case iPhone6 = "{375, 667}"
case iPhone6Plus = "{414, 736}"
}``````

``````let a = Devices.iPhone5
let b = a.rawValue
print("the phone size string is \(a), width is \(b.width), height is \(b.height)")
// prints : the phone size string is iPhone5, width is 320.0, height is 568.0``````

### 对枚举的关联值进行比较

``````enum Trade {
case Sell(stock: String, amount: Int)
}
switch (lhs, rhs) {
where stock1 == stock2 && amount1 == amount2:
return true
case let (.Sell(stock1, amount1), .Sell(stock2, amount2))
where stock1 == stock2 && amount1 == amount2:
return true
default: return false
}
}``````

### 自定义构造方法

``````enum Device {
case AppleWatch
static func fromSlang(term: String) -> Device? {
if term == "iWatch" {
return .AppleWatch
}
return nil
}
}``````

``````enum Device {
case AppleWatch
init?(term: String) {
if term == "iWatch" {
self = .AppleWatch
}
return nil
}
}``````

``````enum NumberCategory {
case Small
case Medium
case Big
case Huge
init(number n: Int) {
if n < 10000 { self = .Small }
else if n < 1000000 { self = .Medium }
else if n < 100000000 { self = .Big }
else { self = .Huge }
}
}
let aNumber = NumberCategory(number: 100)
print(aNumber)
// prints: "Small"``````

### 对 Objective-C 的支持

``````enum Trade {
case Sell(stock: String, amount: Int)
}

// 这个类型也可以定义在 Objective-C 的代码中
var type: Int
var stock: String
var amount: Int
init(type: Int, stock: String, amount: Int) {
self.type = type
self.stock = stock
self.amount = amount
}
}

switch self {
return OTrade(type: 0, stock: stock, amount: amount)
case let .Sell(stock, amount):
return OTrade(type: 1, stock: stock, amount: amount)
}
}

switch (source.type) {
case 1: return Trade.Sell(stock: source.stock, amount: source.amount)
default: return nil
}
}
}``````

## Swift 标准库中的枚举

Bit 这个枚举有两个值，OneZero。它被作为 `CollectionOfOne<T>` 中的 `Index` 类型。

FloatingPointClassification 这个枚举定义了一系列 IEEE 754 可能的类别，比如 `NegativeInfinity`, `PositiveZero``SignalingNaN`

Mirror.AncestorRepresentation Mirror.DisplayStyle 这两个枚举被用在 Swift 反射 API 的上下文当中。

Optional 这个就不用多说了

Process 这个枚举包含了当前进程的命令行参数(`Process.argc`, `Process.arguments`)。这是一个相当有趣的枚举类型，因为在 Swift 1.0 当中，它是被作为一个结构体来实现的。

## 实践用例

### 错误处理

Swift 的枚举特别适用于构建一组相关的错误状态，可以通过关联值来为其增加额外的附加信息。

1. JSON 数据缺少某些最终模型所需要的键(比如你的模型有一个 `username` 的属性，但是 JSON 中缺少了)
2. 存在类型不匹配，比如说 `username` 需要的是 String 类型，而 JSON 中包含的是 `NSNull`6

``````enum DecodeError: ErrorType {
case TypeMismatch(expected: String, actual: String)
case MissingKey(String)
case Custom(String)
}``````

``````enum APIError : ErrorType {
// Can't connect to the server (maybe offline?)
case ConnectionError(error: NSError)
// The server responded with a non 200 status code
case ServerError(statusCode: Int, error: NSError)
// We got no data (0 bytes) back from the server
case NoDataError
// The server response can't be converted from JSON to a Dictionary
case JSONSerializationError(error: ErrorType)
// The Argo decoding Failed
case JSONMappingError(converstionError: DecodeError)
}``````

### 观察者模式

``````enum Change {
case Insertion(items: [Item])
case Deletion(items: [Item])
case Update(items: [Item])
}``````

### 状态码

``````enum HttpError: String {
case Code401 = "Unauthorized"
case Code402 = "Payment Required"
case Code403 = "Forbidden"
}``````

### 结果类型映射(Map Result Types)

``````enum JSON {
case JSONString(Swift.String)
case JSONNumber(Double)
case JSONObject([String : JSONValue])
case JSONArray([JSONValue])
case JSONBool(Bool)
case JSONNull
}``````

### UIKit 标识

``````enum CellType: String {
case ButtonValueCell = "ButtonValueCell"
case UnitEditCell = "UnitEditCell"
case LabelCell = "LabelCell"
case ResultLabelCell = "ResultLabelCell"
}``````

### 单位

``````enum Liquid: Float {
case ml = 1.0
case l = 1000.0
func convert(amount amount: Float, to: Liquid) -> Float {
if self.rawValue < to.rawValue {
return (self.rawValue / to.rawValue) * amount
} else {
return (self.rawValue * to.rawValue) * amount
}
}
}
// Convert liters to milliliters
print (Liquid.l.convert(amount: 5, to: Liquid.ml))``````

### 游戏

``````enum FlyingBeast { case Dragon, Hippogriff, Gargoyle }
enum Horde { case Ork, Troll }
enum Player { case Mage, Warrior, Barbarian }
enum NPC { case Vendor, Blacksmith }
enum Element { case Tree, Fence, Stone }

protocol Hurtable {}
protocol Killable {}
protocol Flying {}
protocol Attacking {}
protocol Obstacle {}

extension FlyingBeast: Hurtable, Killable, Flying, Attacking {}
extension Horde: Hurtable, Killable, Attacking {}
extension Player: Hurtable, Obstacle {}
extension NPC: Hurtable {}
extension Element: Obstacle {}``````

### 字符串类型化

``````enum DetailViewImages: String {
case Background = "bg1.png"
case Sidebar = "sbg.png"
case ActionButton1 = "btn1_1.png"
case ActionButton2 = "btn2_1.png"
}``````

### API 端点

Rest API 是枚举的绝佳用例。它们都是分组的，它们都是有限的 API 集合，并且它们也可能会有附加的查询或者命名的参数，而这可以使用关联值来实现。

``````enum Instagram {
enum Media {
case Popular
case Shortcode(id: String)
case Search(lat: Float, min_timestamp: Int, lng: Float, max_timestamp: Int, distance: Int)
}
enum Users {
case User(id: String)
case Feed
case Recent(id: String)
}
}``````

Ash Furrow的Moya框架就是基本这个思想，使用枚举对 rest 端点进行映射。

### 链表

Airspeed Velocity有一篇极好的文章说明了如何使用枚举来实现一个链表。那篇文章中的大多数代码都超出了枚举的知识，并涉及到了大量其它有趣的主题9，但是，链表最基本的定义是类似这样的(我对其进行了一些简化)：

``````enum List {
case End
indirect case Node(Int, next: List)
}``````

Airspeed Velocity 还写过一篇超赞的博客，关于如何使用 Swift 的间接枚举类型来实现红黑树，所以如果你已经阅读过关于链表的博客，你可能想继续阅读这篇关于红黑树的博客

## 局限

### 提取关联值

David Owens写过一篇文章，他觉得当前的关联值提取方式是很笨重的。我墙裂推荐你去看一下他的原文，在这里我对它的要旨进行下说明：为了从一个枚举中获取关联值，我们必须使用模式匹配。然而，关联值就是关联在特定枚举 case 的高效元组。而元组是可以使用更简单的方式来获取它内部值，即 `.keyword 或者 .0`

``````// Enums
enum Ex { case Mode(ab: Int, cd: Int) }
if case Ex.Mode(let ab, let cd) = Ex.Mode(ab: 4, cd: 5) {
print(ab)
}
// vs tuples:
let tp = (ab: 4, cd: 5)
print(tp.ab)``````

### 相等性

``````// Int 和 String 是可判等的, 所以 Mode 应该也是可判等的
enum Ex { case Mode(ab: Int, cd: String) }

// Swift 应该能够自动生成这个函数
func == (lhs: Ex.Mode, rhs: Ex.Mode) -> Bool {
switch (lhs, rhs) {
case (.Mode(let a, let b), .Mode(let c, let d)):
return a == c && b == d
default:
return false
}
}``````

### 元组(Tuples)

``````enum Devices: (intro: Int, name: String) {
case iPhone = (intro: 2007, name: "iPhone")
case AppleTV = (intro: 2006, name: "Apple TV")
case AppleWatch = (intro: 2014, name: "Apple Watch")
}``````

### 默认关联值

``````enum Characters {
case Mage(health: Int = 70, magic: Int = 100, strength: Int = 30)
case Warrior(health: Int = 100, magic: Int = 0, strength: Int = 100)
case Neophyte(health: Int = 50, magic: Int = 20, strength: Int = 80)
}``````

|--------------------------------------------------------------------
* 这里有精选的技术分享，也有程序猿的日常
* 技术， 面经，转型，成长，欢迎一起参与讨论
* https://blog.csdn.net/itchosen
---------------------------------------------------------------------|

array高级用法 swift 相关内容