75142913在线留言
【基础篇】5 枚举(enum)的使用详解_IOS开发_网络人

【基础篇】5 枚举(enum)的使用详解

Kwok 发表于:2021-02-04 14:04:07 点击:50 评论: 0

前面4篇内容已把swift的基本数据类型介绍了一下,这篇内容将对swift这门语言创建自定义数据类型的能力的介绍。

枚举简单的说也是一种数据类型,通常我们把枚举嵌入到结构体(struct)和类(class)里使用,枚举这种数据类型只包含自定义的特定数据,它是一组有共同特性的数据的集合。枚举在后期的SwiftUI中配置参数中大量的会用到(选项类),所以我们需要深入的了解枚举为后面APP开发打下基础。

一、定义基本枚举

定义枚举的方式是在enum关键字后面跟上自己定义的枚举名字,枚举至少要包含1个case语句,表示枚举的可能值。枚举的名字一般以大写字母开头,如果要用到多个单词需要使用驼峰命名法。

//定义一个性别的枚举
enum Sex{
	case male //男
	case female//女
}
//实例化枚举
var Toilet:Sex = Sex.male

switch Toilet{
	case .male:
		print("你进入的是男厕所")
	case .female:
		print("你进入的女男厕所")	
}

上面是使用完整的代码实例化枚举,实际开发中更多的是使用类型推导来实例化。如:var Toilet = Sex.female即可,如果要再次改变Toilet的值的时候我可以省略Sex即 Toilet = .male即可,因为编译器已经知道了变量的类型。

可以使用一个case定义多个,上面的代码可以简写为:

enum Sex{
	case male,female
}

在 http://www.55mx.com/ios/100.html 结构控制里有写到swift里的switch必须覆盖到所有的情况。而上面的枚举却未使用default语句来覆盖未知的情况,是因为编译器也知道枚举类型的情况是固定的,所以我们不需要使用default来覆盖。使用枚举的时候我们尽量不需要使用默认处理。如果枚举的选项有变化我们可以通过编译的时候及时发现错误来解决问题。

二、使用if来检查枚举的值

var Toilet = Sex.male //实例化枚举
if Toilet != .female{
	print("你进错厕所了~")
}

三、枚举的原始值

可以通过.rawValue属性查看枚举的成员原始值,但有一个前提是在定义枚举的时候需要指定枚举元素的类型(可以使用内建类型和字符串)。

//定义一个性别的枚举
enum Sex:String{
	case male 
	case female = "女"
}
var Toilet = Sex.male //实例化枚举
print(Toilet.rawValue)//male
print(Sex.female.rawValue)//女

上面代码中“女”为指定的原始值(也叫初始值),原始值不是必须的,如果省略了原始值,swift会使用成员的本身的名字(male)。

原始值的主要作用是存储或者传输枚举,如果我们定义了一个边框,边框的宽度默认值就是枚举的原始值,只要我们不去修改它,它就会跟随定义的值。每个带原始值的枚举都可以使用rawValue参数创建,并返回可空枚举。

//定义一个性别的枚举
enum Sex:String{
	case male = "男"
	case female = "女"
}

var Toilet = Sex.male //实例化枚举
if let Toilet = Sex(rawValue:"女"){
	print(Toilet) //打印:female
}else{
	print("转化的原始值不存在~")
}

上面通过了原始值"女"及rawValue参数成功转化了。如果原始值不存(if let Toilet = Sex(rawValue:"人妖"))语句会执行else语句块的内容。

枚举类型如果设置为Int类型并没有指定初始值的时候,编译器会默认从0开始为每个成员指定一个初始值。

如果指定了第1个初始值,就会按第1个的顺序累加赋值:

enum Month: Int {
    case one = 2,two,three,four,five,six
}
print(Month.six.rawValue)//打印:7

四、枚举的方法

很多程序语言方法都是和类(class)关联的,但是swift里的枚举是可以与方法关联的,我们可以增加一个内部函数来自动判断。

//定义一个性别的枚举
enum Sex:String{
	case male = "男"
	case female = "女"
	func Toilet(name:String){
		switch self{
			case .male:
			print(name + "进入了男厕所")
			case .female:
			print(name + "进入了女厕所")
		}
	}
}

var jack = Sex.male //实例化枚举

//调用枚举里的方法
jack.Toilet(name:"张三")//张三进入了男厕所

上面代码因为是在枚举的内部,表面上是只接受一个name参数,实际上它还有一个隐式参数self,类型是Sex,所有swift的方法都会有self参数(类型其它语言的this)。

如果我们需要在方法里修改self需要在定义函数的时候加上:mutating关键字修饰。

//定义一个性别的枚举
enum Sex:String{
	case male = "男"
	case female = "女"
	mutating func toggle(){
		switch self{
			case .male:
			self = .female
			case .female:
			self = .male
		}
	}
}

var jack = Sex.male //实例化枚举
print(jack)//male
jack.toggle() //调用枚举里的方法
print(jack)//female

selft的取值范围被限制到了枚举的范围以内。

5、枚举关联值

关联值能让数据附在枚举实例上,不同的成员可以有不同类型的关联值。枚举关联值是利用了元组类型实现的。一般情况下我们都会使用命名的元组来做为关联值,因为在使用的时候我们会更能理解这个值的意义。

enum map{
	case coordinate(x:Double,y:Double)//定义一个坐标
}
var beijing = map.coordinate(x:0,y:1)
print(beijing)//coordinate(x: 0.0, y: 1.0)

 下面我们利用关联值计算一下图片的面积。

//定义图形区域枚举
enum MeasureArea{
	case square(side:Double) //正方形取1个边长
	case rectangle(width:Double,height:Double) //长方形取2个边长
	//计算图形面积的方法
	func area() -> Double{
		switch self{
		case let .square(side:side):
			return side*side
		case let .rectangle(width:w,height:h):
			return w*h
		}
	}	
}
var Myarea = MeasureArea.square(side:5)//正方形
print(Myarea.area())//打印结果:25.0,因为(5.0*5.0=25.0)
Myarea = .rectangle(width:5,height:3)//长方形
print(Myarea.area())//打印:15.0

下面再看一下实例:

enum Student{
    case name(String)
    case achie(Int,Int,Int)
}
var studname = Student.name("张三")
var studachie = Student.achie(61,62,65)
switch studname {
case .name(let studName):
    print("名字: " + studName)
case .achie(let chinese, let english, let math):
    print(chinese,english,math)//保存的成绩
}

 五、递归枚举

上面介绍了枚举使用关联值,我们可以通过了解计算机科学知道常见的数据结构中有一个“树“形结构,我们生活常见的树形结构就是家庭族谱,所以电视里常常会说”开枝散叶“就是家族的发展。我们可以通过枚举类型里的递归对族谱建模。 

indirect enum FamilyTree{
	case unknownParents//未知父辈
	case oneParent(name:String,ancestors:FamilyTree)//有一个已知的长辈
	//有2个已知的长辈
	case twoParent(fatherName:String,fatherAncestors:FamilyTree,
				  motherName:String,motherAncestors:FamilyTree)
}
let myFamily = FamilyTree.twoParent(
	fatherName:"张三",fatherAncestors: .oneParent(name:"张三爹",ancestors:.unknownParents),
	motherName: "李翠花",motherAncestors:.unknownParents
)
print(myFamily)//打印族谱

值得注意的是,其实不需要把整个枚举标记为间接,也可以把递归的成员单独标记为间接即可。改下代码:

enum FamilyTree{
	case unknownParents
	indirect case oneParent(name:String,ancestors:FamilyTree)
	indirect case twoParent(fatherName:String,fatherAncestors:FamilyTree,
				motherName:String,motherAncestors:FamilyTree)
}

六、CaseIterable协议

 CaseIterable 是一个支持自动合成的 -able 协议,合成的协议Equatable 和 Hashable以及 Codable等。

enum Weekday : String, CaseIterable {
    case monday, tuesday, wednesday, thursday, friday
}

print(Weekday.allCases)//打印枚举值的数组

使用.allCases.count返回枚举数也可以配置for遍历枚举的值。

除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/103
标签:枚举ebumKwok最后编辑于:2021-03-12 11:12:21
0
感谢打赏!

《【基础篇】5 枚举(enum)的使用详解》的网友评论(0)

本站推荐阅读

热门点击文章