首页 > 代码库 > Swift的闭包,枚举,类和结构体

Swift的闭包,枚举,类和结构体

闭包(Closures)


使用过其它语言的应该对代码块并不陌生,Swift中的闭包与C,OC中的Block相似。
表示自包括的函数代码块。能够在代码中传递和使用。

而且能够捕获和存储上下文的变量以及常量值,Swift会为你进行捕获相关的内存操作。


上一篇文章提到的函数。也是一种特殊的闭包。详细在:
全局函数是有名字可是不会捕获不论什么值的闭包。
嵌套函数是有名字且能够捕获域内值的闭包。
闭包表达式是利用轻量级语法写的能够捕获上下文值的匿名闭包。

基本的语法

表达式的一般语法以及简化过程
技术分享

上面罗列了同一个行为的五种写法,也标明了简化方法适用的情景。

跟随闭包


上面那个闭包若使用跟随闭包的方式来写,则表现为:
reversed = sort(names) {$0 > $1}

通常我们会把具有多行的闭包表达式写入跟随闭包。

比如Array的map方法能够对数组内的每个元素调用一次闭包。返回一个新的数组。
技术分享

这里捕获了numbers数组中的每一个值并将output映射到一个新的strings数组中。



值捕获


闭包能够在其上下文捕获一些值,即使原域已经不存在。

上面提到嵌套函数是有名字能够捕获域内值的闭包。

Swift中最简单的闭包形式即是嵌套函数。

技术分享

这里定义了一个嵌套函数makeIncrementor,里面记录了一个变量runningTotal,嵌套在里面的函数能够捕获这个值并将其持有保留住。

技术分享

可是假设新声明了一个同样函数的变量/常量引用,则其runningTotal并不共享
技术分享


闭包是引用类型,上面声明的常量是指向闭包内容的一个引用,而并不是闭包内容本身。



枚举


Swift的枚举十分灵活,case中的值能够是字符串。字符。整型或者浮点型。

而且能够指定不论什么类型的相关值存储到枚举成员中。

在Swift里,枚举是一等类型(first-class),它支持类所支持的特性(除了继承)。你能够为它定义一些函数让其富有行为等等。


基本的语法

技术分享

当我们已经确定了其是CompassPoint的时候,能够直接使用.Value省略枚举名的形式赋值。

switch匹配
技术分享

相关值

前面提到过。我们能够为其指定随意类型的相关值存储到枚举成员中。
来看以下这个样例
技术分享

我们给BarCode枚举存储了一些对应case的相关值,而且能够利用绑定值的方式去訪问它,如在switch中定义了个常量identifier来获取Barcode中QRCode的相关值。


原始值

在Swift中,枚举并不会像c,objective-c中的枚举在你未声明枚举值的情况下隐式的赋值0,1。2...仅仅有我们给其赋值时才会推測其值。可是也仅限于Int。
Swift为其定义了方法来訪问原始值toRaw()或者通过fromRaw(value)訪问其枚举成员。
技术分享

因为我们的枚举中并没有5相应的成员,所以其为nil。但假设换为3。则是Green。

那假设枚举成员是String呢?会不会也会推測值?当然是不太可能了- -
编译器会报错
技术分享

非integer必需要给其赋值才干够。


类与结构体


定义,实例声明与属性


技术分享

因为这里并没有设置自己定义的指定构造器。所以能够直接使用默认的方式()来初始化一个实例。


訪问设置属性则使用点语法,只是与Ojbective--C不同的是,Swift同意对结构体的子属性直接赋值。

另外一个不同则是Swift类不须要.h接口文件。

技术分享

在OC中我们想改动Rect.Origin的x值常常须要赋一个新的origin给rect,而Swift中则能够直接改动了。


在Swift中结构体,枚举和类都能够通过写一些成员函数来为其加入行为。

构造时则稍有不同,结构体能够为其提供逐一成员构造器。
技术分享

这是系统自己主动提供的。而类则没有提供。

值类型和引用类型


结构体,枚举和类另外主要不同的一点是类型。

结构体和枚举为值类型,类则是引用类型。

值类型指在赋值传递的时候,系统会自己主动为其拷贝一个新值并传递给新声明的变量或常量。
技术分享

我们注意在将hd赋值给cinema后马上cinema的width进行了改动,可是再訪问hd.width还是原来的值1920.说明仅仅是将hd的拷贝赋给了cinema而并非hd本身。

引用类型这是将新的变量或常量指向了原来的对象,而并不是拷贝对象值之后进行赋值。
技术分享

这里改动了frameRate,再訪问原来变量的frameRate发现也发生了变化。原因在于他们都指向了同一块堆内存。



在Swift中。判定引用相等引人了一个恒等符号"==="。来判定是否引用同一实例,不引用同一实例则为"!=="(不等价于)
那么"==="和"=="的不同在于哪里呢?
等价于("===")表示两个类类型的常量或变量引用同一个实例。

而"=="表示两个实例的值是否相等。判定须要遵照类设计者定义的判定标准。


因为结构体是值类型。我们不使用等价于进行推断。



类和结构体的异同和选择


首先来看类和结构体的同样点:
定义属性用于存储值
定义方法用于提供功能
定义附属脚本(subscript)用于訪问值
定义构造器用于初始化值和配置
通过扩展以添加默认实现的功能
符合协议以对某类提供标准功能

不同点在于:(类)
继承同意一个类继承还有一个类的特征
类型转换同意在执行时检查和解释一个类实例的类型
解构器(析构过程会提到)同意一个类实例释放不论什么其所被分配的资源
引用计数同意对一个类的多次使用

则我们通常在下列情况下考虑结构体:
用来封装少量相关简单数据值
估计数据传递会被拷贝而不是引用
结构体中的值类型属性也会被拷贝
不须要继承或被继承特征和行为

集合类型的赋值和拷贝行为


上面说到了值类型和引用类型。在Swift中,集合类型字典和数组在后台均以结构体实现,可是他们的情况略微有些特殊。
尽管通常值类型的赋值行为都是通过拷贝实现的,我们也不须要害怕过多使用内存而带来的性能问题。Swift会管理全部的值拷贝以确保性能最优化。

字典的赋值和拷贝行为

字典的key/value中。若其为值类型则拷贝值。引用类型则拷贝引用。
技术分享

数组的赋值和拷贝行为


相比字典数组要复杂的多,当操作数组内容时,数组能提供接近C语言的性能。而且保证拷贝仅仅有在必要时发生。

那么必要时是什么时候呢?是改变数组长度的时候,比如调用了append(), insert(), remove()等函数。数组的拷贝才会发生。不改变时则属于引用传递。

技术分享

有的时候我们想确保数组的唯一性,这时能够调用unshare方法使其变成唯一拷贝。强制拷贝则使用copy方法。可是copy在不论什么情况下都会创建新的拷贝,而unshare则会确保唯一引用。



在判定数组是否同样时我们也能够使用"==="来判定两个数组是否共用同样的空间或者元素。

技术分享

由于他们都非共用空间,所以返回都是false.



有关闭包,枚举,结构体和类的基础知识都解说完成。

欢迎勘误和讨论。


Swift的闭包,枚举,类和结构体