概述
iOS 中的枚举是一种常用的数据类型,可以帮助我们在编写代码时更好地组织和管理相关的常量值。在本文中,我们将从 OC 与 Swift 两个方向的出发,介绍枚举在 iOS 开发中的基础用法以及一些高级用法
1. OC 中的枚举
1.1 枚举的定义
OC 中的枚举可以通过 enum 关键字来定义,如下所示:
typedef enum {
kGenderMale,
kGenderFemale,
kGenderUnknown
} Gender;
上述代码定义了一个枚举类型 Gender,其中包含了三个常量值:kGenderMale、kGenderFemale 和 kGenderUnknown。这些常量值都被默认赋予整数值,起始值为 0,依次递增。
在使用枚举时,可以直接通过枚举常量值来获取其对应的整数值,例如:
Gender gender = kGenderMale;
int intValue = gender; // intValue = 0
也可以直接将整数值赋给枚举变量,例如:
Gender gender = 1; // gender = kGenderFemale
1.2 位移枚举
除了普通枚举之外,OC 还提供了一种特殊的枚举类型,称之为“位移枚举(Option Set)”。位移枚举可以表示一组状态,每个状态都是独立的,可以通过按位或(|)运算进行组合。
例如,下面的代码定义了一个 UIViewAutoresizing 的位移枚举类型,表示 UIView 自动调整大小时可以采用的一组可选项:
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
在使用位移枚举时,可以使用按位或(|)运算符将多个枚举常量组合起来,例如:
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
2. Swift 中的枚举
2.1 枚举的定义
在 Swift 编程语言中,枚举是一种很有用的数据类型,可以用来表示一组相关联的值。其在 Swift 中有许多高级特性,如原始值、关联值以及嵌套枚举等
2.2 枚举的原始值
Swift 中的枚举可以包含原始值,原始值可以是任何一种数据类型,如整型、浮点型等。
例如,下面的代码定义了一个用于表示请求方式的 Enum 类型:
/// 为 RequestMethod 枚举指定字符串类型的原始值
enum RequestMethod: String {
case get = "get"
case post = "post"
case upload = "upload"
case download // 等价于 download = "download"
}
对于 String 类型的 Raw Value,若没指定值,默认为 case name,
对于 Int/Float 类型,默认值从 0 开始,依次 +1
通过 rawValue 属性可以获取 case 对应的 原始值
let value = RequestMethod.get.rawValue
2.3 枚举的关联值
Swift 中的枚举可以包含关联值,关联值可以为枚举成员提供更多的信息,且可为关联值提供默认值,例如:
enum Shape {
/// 圆形
case circle(radius: Float = 5.0)
/// 矩形
case rectangle(width: Float, height: Float)
/// 正方形
case square(side: Float)
}
// 创建一个 Shape 枚举变量,并指定其为圆形,半径为 5
let shape = Shape.circle(radius: 15)
在这个例子中,枚举 Shape包含三个不同的枚举值,分别是:
circle:表示一个圆形,其关联值radius表示圆的半径,并提供默认值rectangle:表示一个矩形,其关联值width和height分别表示矩形的宽度和高度square:表示一个正方形,其关联值side表示正方形的边长
这种使用关联值的方式可以使枚举类型更加灵活,能够表示更加复杂的数据结构。在实际使用中,可以根据具体需求选择不同的关联值类型,并进行相关的处理。
2.4 枚举的遍历
有时,我们希望遍历 Enum 的所有 cases,或是获取第一个 case,此时 CaseIterable 派上用场了
public protocol CaseIterable {
/// A type that can represent a collection of all values of this type.
associatedtype AllCases : Collection = [Self] where Self == Self.AllCases.Element
/// A collection of all values of this type.
static var allCases: Self.AllCases { get }
}
在CaseIterable协议中,associatedtype 关键字用于声明一个关联类型,让遵循该协议的类型来指定该类型的具体实现。其中,AllCases 就是一个关联类型,它被声明为一个集合类型,默认值为 [Self],也就是一个由遵循该协议的类型本身组成的数组。
此外,where 语句也可以对关联类型进行约束,限制遵循该协议的类型的实现方式。在这里,where 语句对 AllCases 进行了两个约束条件:
Self == Self.AllCases.Element:表示Self和Self.AllCases.Element这两个类型必须相等,也就是说Self本身就是集合类型中的元素类型。Self.AllCases必须是Collection协议的遵循者:这个约束条件表示AllCases必须是一个集合类型,并且遵循Collection协议。
总体而言,AllCases 是一种在枚举类型中常用的关联类型。通过使用 AllCases,我们可以方便地遍历枚举类型中的所有成员,并以数组的形式访问它们。
enum MyEnum: String, CaseIterable {
case case1 = "case1"
case case2
case case3
}
let case1 = MyEnum.allCases.first
for value in MyEnum.allCases {
print(value)
}
注意:对于有关联值的枚举,不会自动合成 allCases,因为关联值没法确定,此时,需要手动实现 CaseIterable 协议
2.5 嵌套枚举
Swift 中的嵌套枚举可以将一个枚举类型定义在另一个枚举类型的内部,从而形成更加复杂和有层次的枚举结构。下面是一个简单的示例:
enum Family {
case father(name: String)
case mother(name: String)
enum Child {
case son(name: String, age: Int)
case daughter(name: String, age: Int)
}
}
let parents = Family.father(name: "XXX")
let child = Family.Child.son(name: "XXX", age: 8)
在这个例子中,Family 是一个嵌套枚举类型,它包含了两个枚举值 father 和 mother,每个值都带有一个关联值,表示家庭中的父亲和母亲。此外,Family 还定义了一个名为 Child 的嵌套枚举类型,该类型表示家庭中的孩子,具有两个不同的枚举值 son 和 daughter,每个值都带有两个关联值,分别表示孩子的姓名和年龄。
可以看到,在 Swift 中使用嵌套枚举可以使枚举类型更加灵活和具有层次感,能够更好地表达复杂的数据结构