07、enum枚举
1、定义enum
很多时候,我们需要用一组特定的值,来表达一个公共的含义。例如用1,2,3,4表示东、南、西、北,面对“把一组有相关意义的值定义成一个独立的类型”这样的任务,Swift为我们提供了一种类型安全的方式,叫做enum。
1.1 不设置rawValue
enum Week {
case MON
case TUE
case WED
case THU
case FRI
case SAT
case SUN
}
简写:
enum Week {
case MON,TUE,WED,THU,FRI,SAT,SUN
}
print(Week.MON)
type(of: Week.MON) // __lldb_expr_17.Week.Type
没有设置rawValue 无法调用Week.MON.rawValue
1.2 设置rawValue为String类型
01、不绑定默认值。如果我们不想写后面的字符串,也可以简写成如下的形式,默认rawValue是case 后面的值。
enum Week:String {
case MON
case TUE
case WED
case THU
case FRI
case SAT
case SUN
}
02、绑定默认值
enum Week:String {
case MON = "MON"
case TUE = "TUE"
case WED = "WED"
case THU = "THU"
case FRI = "FRI"
case SAT = "SAT"
case SUN = "SUN"
}
print(Week.MON) //
type(of: Week.MON) // __lldb_expr_21.Week.Type
type(of: Week.MON.rawValue) //String.Type
1.3 设置rawValue为整数
和Objective-C不同,Swift的enum默认不会为它的case“绑定”一个整数值。
01、如果不设置默认值,Swift默认为会把Week.MON、Week.TUE、Week.WED、Week.THU、Week.FRI、Week.SAT、Week.SUN绑定为0、1、2、3、4、5、6
enum Week:Int {
case MON
case TUE
case WED
case THU
case FRI
case SAT
case SUN
}
02、绑定默认值
enum Week:Int {
case MON = 2
case TUE = 3
case WED = 4
case THU = 5
case FRI = 6
case SAT = 7
case SUN = 8
}
03、根据第一个值自动推导
enum Week:Int {
case MON = 2
case TUE
case WED
case THU
case FRI
case SAT
case SUN
}
print(Week.MON)
type(of: Week.MON) //__lldb_expr_23.Week.Type
type(of: Week.MON.rawValue) //Int.Type
2、关联值(Associated value)
在Swift里,我们可以给每一个case“绑定”不同类型的值。我们管这样的值叫做associated values。
enum HttpAction {
case get
case post(String)
case delete(Int,String)
}
var action1 = HttpAction.get
var action2 = HttpAction.post("lichangan")
switch action1 {
case .get:
print("HTTP GET")
case .post(let msg):
print("\(msg)")
case let .delete(id, data):
print("id = \(id),data = \(data)")
}
3、enum是值类型,也是引用类型
在Swift里,enum默认也是一个值类型,也就说,每一个enum对象,都只能有一个owner,因此,你无法创建指向同一个enum对象的多个引用。
但有一种特殊的情况,可以改变enum的这个属性
enum List {
case end
indirect case node(Int, next: List)
}
我们可以使用indirect修饰一个case,这样当一个List为case node时,它就变成了一个引用类型,多个case node可以指向同一个List对象:
let end = List.end
let list1 = List.node(1, next: end)
let list2 = List.node(2, next: end)
此时,list1和list2就指向了同一个end对象。
4、enum中的函数
Swift中的枚举也可以包含方法,可以是实例方法也可以是类方法。
enum Week:Int {
case MON,TUE,WED,THU,FRI,SAT,SUN
mutating func nextDay() {
if self == .SUN {
self = .MON
}else {
self = Week.init(rawValue: self.rawValue + 1)!
}
}
static func creator(){
print("lichangan")
}
}
5、enum中的属性
Swift中允许在枚举中包含计算属性和类型属性,但不能包含存储属性。
enum Week:Int {
case MON = 2
case TUE
case WED
case THU
case FRI
case SAT
case SUN
//计算属性
var firstDay:Week {
return .MON
}
//类型属性
static let lastDay:Week = .SUN
}
6、与OC汇编
6.1 OC调用Swift中的枚举
如果想要在OC中使用Swift枚举要求会很严格:
- 使用@objc标记
- 类型必须是Int,也就是Swift的rawValue
- 必须导入import Foundation
import Foundation
@objc enum Week: Int{
case MON, TUE, WED, THU, FRI, SAT, SUN
}
此时编译后就可以正在project-Swift.h中看到转换后的对应的OC枚举:
6.2 Swift中调用OC
6.2.1 NS_ENUM
NS_ENUM(NSInteger, OCENUM){
Value1,
Value2
};
如果使用NS_ENUM创建的枚举会自动转换成swift中的enum
可以在ocfileName.h中查看转换后的枚举:
使用的话需要在桥接文件中导入OC头文件,然后在swift中使用:
let value = OCENUM.Value1
6.2.2 使用typedef enum
typedef enum {
Enum1,
Enum2,
Enum3
}OCENum;
如果使用typedef enum这种形式的枚举,会转换成结构体,同样可以在ocfileName.h中查看转换后的结果,转换后的代码如下:
可以看到里面有一个rawValue属性,以及init方法。还遵守了Equatable, RawRepresentable两个协议。
使用的话也是需要导入头文件:
let num = OCEnum(0)
let num1 = OCEnum.init(0)
let num2 = OCEnum.init(rawValue: 3)
print(num)
<!--打印结果-->
OCNum(rawValue: 0)
这里我们只能通过init方法去初始化,不能访问枚举中的变量。
6.2.3 使用typedef NS_ENUM
typedef NS_ENUM(NSInteger, OCENUM){
OCEnumInvalid = 0,
OCEnumA = 1,
OCEnumB,
OCEnumC
};
使用typedef NS_ENUM也会自动转换为Swift的枚举,转换后的代码如下:
使用也是需要导入头文件:
let ocenum = OCENUM.OCEnumInvalid
let ocenumRawValue = OCENUM.OCEnumA.rawValue
6.3 混编时需要使用String类型的枚举
Swift中需要使用String类型的枚举,但是又要与OC混编,暴露给OC使用。
如果直接声明为String类型编译时不会通过的,这里只能弄个假的。Swift中的枚举还是声明为Int,可以在枚举中声明一个变量或者方法,用于返回想要的字符串。
@objc enum Week: Int{
case MON, TUE, WED
var value: String?{
switch self {
case .MON:
return "MON"
case .TUE:
return "TUE"
case .WED:
return "WED"
default:
return nil
}
}
func weekName() -> String? {
switch self {
case .MON: return "MON"
case .TUE: return "TUE"
case .WED: return "WED"
default:
return nil
}
}
}
用法:
<!--OC用法-->
Week mon = WeekMON;
<!--Swift用法-->
let value = Week.MON.value
let value1 = Week.MON.weekName()