今天的博客算是比较基础的,仍是那句话,基础这东西在何时都是最重要的。说到函数,只要是写过程序就确定知道函数是怎么回事,今天就来讨论一下Swift中的函数的特性以及Swift中的闭包。今天的一些小实例中回类比一下Objective-C中的函数的写法等等。Swift中的函数仍是有许多好用的特性的,好比输入参数,使用元组返回多个值, 定义形参名,设定默认参数以及可变参数等等一些好用的特性。而在Swift中的闭包就是Objective-C中的Block, 除了语法不通外,二者的用法是同样的。废话少说,开始今天的主题,先搞一搞Swift中的函数,而后在搞一搞Swift中的闭包。编程
一.Swift中的函数swift
1. 函数的定义与使用数组
在介绍Swift中的函数以前,我想用Objective-C中的一个简单的加法函数来做为引子,而后类比着实现一下Swift中相同功能的函数。关于函数定义就比较简单了,就是一些语法的东西,下面的代码片断是Objc中求两个整数之和的函数,并返回两个数的和。闭包
1框架 2编程语言 3ide |
|
函数的功能比较简单了,就是把两个整数传进来,而后返回两个整数的和。接下来将用Swift语言实现,也好经过这个实例来熟悉一下Swift语言中定义函数的语法。下方是Swift语言中求两个整数之和的函数。语法比较简单了,在Swift中定义函数,咱们会使用到关键字func来声明函数。
1 2 3 4 |
|
用文字来描述Swift定义基本函数的语法就是: func 函数名 (形参列表) -> 返回值类型 { 函数体},这样你就能够定义一个函数了。固然,函数定义时还有好多其余的用法,下面会详细介绍。上面函数的调用方法以下:
1 |
|
2. 函数中的形参列表
关于函数中的形参列表仍是有必要提上一嘴的,由于形参列表做为函数数据源之一,因此把参数列表好好的搞一搞仍是颇有必要的。参数列表也有不少好用的使用方式,接下来详细的介绍一下函数的形参列表。
(1) 默认的形参是常量(let)
在函数的形参列表中,默认的形参是常量。也就是至关于用let关键字对形参进行修饰了。咱们能够作个试验,把上面加法函数作一个修改,在加法函数中对number1进行加1操做,你会获得一个错误,这个错误的大致意思就是“number1是不可被修改的,由于它是let类型的常量”。而且编译器还给人出了Fix-it(修复)的方案,就是在number1前面使用var关键字进行修饰,使其成为变量,这样才能够修改其值。
上面说这么多,一句话:形参默认是常量,若是你想让其是变量,那么你可使用var关键字进行修饰,这样被关键字var修饰的变量在函数中就能够被修改。下方就是报的这个错误,和编译器提供的解决方案。(在Objc中默承认以在函数中改变形参的值)
(2)给形参命名
为了代码的可读性和可维护性,咱们在定义函数时,须要为每一个参数名一个名字,这样调用者见名知意,很容易就知道这个参数表明什么意思了。接下来仍是在上述加法函数中进行修改,为每一个参数名一个名字,并看一下调用方式。修改上面的函数,给第一个形参命名成numberOne, 第二个形参为numberTwo, 下方是修改后的函数。 紧接着sum()函数的调用方式也会有所改变,在调用函数时编译器会给出参数的名称,这样调用者一目了然。
1 2 3 4 5 6 |
|
调用上述函数时,下方是编译器给出的提示,一目了然呢。
关于Swift中参数名的内容,要说明的是在Swift1.0的时候,你能够在参数前面添加上#号,而后参数名就与变量(或者常量)的名字相同,而Swift2.0后这个东西去掉了,由于默认就至关于Swift1.0中添加#号。
(3) 函数的传参与传引用
先暂且这么说着,在C语言的函数中能够给函数传入参数,或者传入实参的内存地址就是所谓的传引用。若是传入的是引用的话,在函数中对值进行修改的话,那么出了函数,这个被修改的值是能够被保留的。在Swift中也是能够的,不过你须要使用inout关键字修饰形参,而且在使用该函数时,用&来修饰。这一点和C语言中相似,&就是取地址符。下方是inout使用的一个小实例。
1 2 3 4 5 |
|
myTestNumber变量通过incrementStepTwo()函数后,其值就会增长2。固然前提是myTestNumber是变量,若是myTestNumber是常量的话,那么对不起,调用该函数就会报错,下面是把var改为let后IDE给的错误提示。错误缘由很显然是你动了一个不应动的值,也就是常量不可再次被修改的。
(4) 不定参数函数
不定参数函数也就是形参的个数是不定的,可是形参的类型必须是相同的。不定形参在使用时怎么取呢?不定个数的形参其实是一个数组,咱们能够经过for循环的形式来遍历出每一个形参的值,而后使用就能够了。下方incrementMultableAdd()函数的形参的个数是不定的,其功能是求多个整数的和。在函数中咱们只需遍历每一个参数,而后把每一个参数进行相加,最后返回所求的和便可。函数比较简单,再此就不在啰嗦了。
(5) 默认形参值
在Swift语言中是支持给形参赋初始值的,这一点在其余一些编程语言中也是支持的。可是Objective-C这么看似古老的语言中就不支持给形参指定初始值,在Swift这门现代编程语言中是支持这一特性的。默认参数要从参数列表后开始为参数指定默认值,否则就会报错。下方就是为函数的形参指定默认参数的示例。一个表白的方法sayLove(), 形参youName默认是“山伯”, 形参loverName默认是“英台”。 紧接着是sayLove函数的三种不一样的调用方式,在调用函数时你能够不传参数,能够传一个参数,固然传两个也是没问题的。
由于函数的每一个参数都是有名字的,在含有默认参数的函数调用时,能够给任意一个参数进行传值,其余参数取默认值,这也是Swift的一大特点之一,具体请看以下简单的代码示例:
3.函数类型
每一个函数都有本身的所属类型,函数类型说白了就是若是两个函数参数列表相同以及返回值类型相同,那么这两个函数就有着相同的函数类型。在Swift中能够定义一个变量或者常量来存储一个函数的类型。接下来将用过一个实例还介绍一下函数类型是个什么东西。
(1) 首先建立两个函数类型相同的函数,一个函数返回两个整数的差值,另外一个函数返回两个整数的乘积。固然这两个函数比较简单,直接上代码:
1 2 3 4 5 6 7 8 |
|
(2) 函数定义好后,接着要定义个一个枚举来枚举每种函数的类型,下面定义这个枚举在选择函数时会用到,枚举定义以下:
1 2 3 4 5 |
|
(3) 接下来就是把(1)和(2)中定义的东西经过一个函数来组合起来。说白了,就是定义个函数来经过枚举值返回这个枚举值所对应的函数类型。有时候说多了容易犯迷糊,就直接上代码得了。下方函数的功能就是根据传进来的枚举值来返回相应的函数类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
(4) 接下来就是使用(3)中定义的函数了,首先咱们须要定义一个相应函数类型((Int, Int) -> Int)的变量来接收choiseCountType()函数中返回的函数类型,而后调用该函数类型变量,在Playground中执行的结果以下:
4.函数嵌套
咱们能够把 3 中的代码使用函数嵌套进行重写,在Swift中是支持函数嵌套的。 因此能够吧3.1和3.2中的函数放到3.3函数中的,因此咱们能够对上述代码使用函数嵌套进行重写。使用函数嵌套重写后的代码以下所示,固然,choiseCountType()函数的调用方式没用发生改变,重写后的调用方式和3.4中的调用方式是同样同样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
二. 闭包
说道Swift中的闭包呢,不得不提的就是Objective-C中的Block, 其实二者是一个东西,使用方式以及使用场景都是相同的。咱们彻底能够类比着Objective-C中的Block来介绍一下Swift中的Closure(闭包)。其实就是匿名函数。接下来的这段内容,先介绍一下Swift中Closure的基本语法,而后在类比着ObjC中的Block窥探一下Closure的使用场景。
1.Closure变量的声明
Closure就是匿名函数,咱们能够定义一个闭包变量,而这个闭包变量的类型就是咱们上面介绍的“函数类型”。定义一个闭包变量其实就是定义一个特定函数类型的变量,方式以下。由于Closure变量没有赋初始值,因此咱们把其声明为可选类型的变量。在使用时,用!强制打开便可。
1 |
|
除了上面的方式外,咱们还用另外一种经常使用的声明闭包变量的方式。那就是使用关键字typealias定义一个特定函数类型,咱们就能够拿着这个类型去声明一个Closure变量了,以下所示
1 2 3 |
|
2. 给Closure变量赋值
给Closure变量赋值,其实就是把一个函数体赋值给一个函数类型的变量,和函数的定义区别不大。可是给闭包变量赋值的函数体中含有参数列表,而且参数列表和真正的函数体之间使用关键字in来分割。 闭包可选变量的调用方式与普通函数没什么两样,惟一不一样的是这个函数须要用!来强制打开才可使用。赋值和调用方式以下。
3. 闭包回调的应用实例
暂且先称做闭包回调吧,其实就是Objc中的Block回调。在Swift中的闭包回调和Objc中的Block回调用法一致,下方将会经过一个实例来介绍一下闭包的应用之一。下方会建立两个视图控制器,咱们暂且称为FirstViewController和SecondViewController。在FirstViewController上有一个Label和一个Button, 这个Button用来跳转到SecondViewController, 而这个Label用来显示从SecondViewController中回调过来的值。 而SecondViewController也有一个TextField和一个Button, 点击Button就会把输入框中的值经过闭包回调回传到FirstViewController而后在FirstViewController上的Label显示。
(1) 构建这个实例的第一步要作的就是使用Stroyboard把咱们所需的控件布局好,而且管理相应的类。固然咱们这个Demo的重点不在于如何去布局控件,如何去关联控件,以及如何去使用控件,因此上述的这些就不作赘述了。这个实例的重点在于如何使用Closure实现值的回调。下方是咱们的控件布局和目录结构的截图,从Storyboard上的控件来看,功能也就一目了然了。点击“FirstViewController” 上的“Go SecondViewController”按钮,就会跳转到 “SecondViewController” 。 在SecondViewController视图上的输入框输入数值,点击Back按钮返回到FirstViewController, 同时把输入框中的文本经过闭包回调的形式回传过来在FristViewController的label上显示。大体就这个简单的功能。
(2)FirstViewController.swift中的内容
FirstViewController.swift中的内容比较简单,就关联一个Label控件和一个按钮点击的事件,点击按钮就会跳转到SecondViewController,具体代码以下,在此就不啰嗦了,请看代码中的注释。下方代码重要的一点是在跳转到SecondViewController时要实现其提供的闭包回调,以便接受回传过来的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
(3) SecondViewController.swift中的内容
SecondViewController.swift中的内容也不麻烦,就是除了关联控件和事件外,还定义了一个闭包类型(函数类型),而后使用这个特定的函数类型声明了一个此函数类型对应的变量。咱们能够经过这个变量来接受上个页面传过来的闭包体,从而把用户输入的值,经过这个闭包体回传到上个页面。具体代码实现以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
(4) 通过上面的步骤这个实例已经完成,接下来就是看一下运行效果的时间了。原本想作成Git动态图的,感受实例功能简单,并且UI上也比较简单,就没作,仍是看截图吧。运行效果的截图以下:
4.数组中经常使用的闭包函数
在Swift的数组中自带了一些比较好用的闭包函数,例如Map, Filter, Reduce。接下来就好好的看一下这些闭包,用起来仍是比较爽的。
(1) Map(映射)
说到Map的用法和功能,不能不说的是若是你使用过ReactiveCocoa框架,那么对里边的Sequence中的Map的使用方式并不陌生。其实二者的使用方法和功能是极为类似的。若是你没使用过RAC中的Map,那也可有可无,接下来咱们先上段代码开看一下数组中的Map闭包函数。
经过上面的代码段以及运行结果,咱们不难看出,map闭包函数的功能就是对数组中的每一项进行遍历,而后经过映射规则对数组中的每一项进行处理,最终的返回结果是处理后的数组(以一个新的数组形式出现)。固然,原来数组中的元素值是保持不变的,这就是map闭包函数的用法与功能。
(2) Filter (过滤器)
Filter的用法仍是比较好理解的,Filter就是一个漏勺,就是用来过滤符合条件的数据的。在ReactiveCocoa中的Sequence也是有Filter的,用法仍是来过滤Sequence中的数据的。而在数组中的Filter用来过滤数组中的数据,而且返回新的数组,新的数组中存放的就是符合条件的数据。Filter的用法以下实例,下方的实例就是一个身高的过滤,过滤掉身高小于173的人,返回大于等于173的身高数据。
(3)Reduce
在ReactiveCocoa中也是有Reduce这个概念的,ReactiveCocoa中使用Reduce来合并消减信号量。在swift的数组中使用Reduce闭包函数来合并items, 而且合并后的Value。下方的实例是一个Salary的数组,其中存放的是每月的薪水。咱们要使用Reduce闭包函数来计算总的薪水。下方是DEMO的截图: