swift的函数与其它编程语言在使用上差不多,但是个性化的苹果公司也做了那么一点点的修改让它变得另类。在实际开发使用中我们需要熟记函数的特点即可。swift的函数可以不返回值、返回单个值、返回多个值、返回一个函数,还可以闭包。
1、标准的函数定义与调用:
通常情况下我们定义的函数在下面的演示代码:
func myFunc(name:String,sex s:Bool)-> String{
return name + "是一个" + (s ? "男" : "女") + "人"
}
print(myFunc(name: "张三", sex: true)) //张三是一个男人
和go语言一样使用func修饰一个myFunc的自定义函数,括号是传入函数里参数1:name:String类型,参数2的sex是变量的tag标签,提升函数的可读性,当然可以不使用。-> 后面就是函数的返回值类型,没有返回值可以不写或者写为->void。
调用函数的时候swift强制要求写上变量参数的名字,如果指定了tag就必须写tag名。
2、无参数与返回值的函数:
func welcome(){
print("欢迎访问55mx.com")
}
3、可变参数(多个不确定参数)
变长参数接受0个或者多个输入值作为参数,一个函数只能有一个可变参数且必须是参数的最后一个,参数在内部以数组的形式存在。
func welcome(names:String...){
for name in names{
print("欢迎" + name + "访问55mx.com")
}
}
welcome(names: "张三","李四","王五")
/*
欢迎张三访问55mx.com
欢迎李四访问55mx.com
欢迎王五访问55mx.com
*/
4、参数默认值
swift的参数可以接受默认值,默认值应该放到参数的后面,如果形参有默认值,那么调用的时候可以省略实参。
func welcome(name:String = "美食圈",url:String = "meishiq.com"){
print("欢迎访问:" + name + url)
}
welcome(name: "网络人", url: "55mx.com") //欢迎访问:网络人55mx.com
welcome() //欢迎访问:美食圈meishiq.com
swift里有一些与其它语言不相同的用法,在实际开发过程中是非常有用的。
1、inout修饰参数:
加上这个参数可以修改函数传入的外部变量值,类似于GO和PHP里的传内存指针。可以通过下面的代码了解使用方法:
var say = "我是:"
func sayScore(_ score: Int , name: inout String){
name += "张三,成绩为:" + String(score)
}
sayScore(99,name:&say)//调用函数和GO一样传say变量的内存地址&say
print(say) //say外部变量的值被函数在内部修改为了:我是:张三,成绩为:99
上面我们说到了函数调用的时候需要写上参数的名字,但这个函数调用的时候直接写了99没有写score参数,是因为我们使用了(_)来忽略参数名,这们可以让我们更灵活的使用函数(自以为是的牵强解释)。
2、函数的嵌套和作用域
嵌套函数是在另一个函数里声明并实现,这个在函数里声明的函数可以访问当前函数的值。
func sum(_ a:Int,_ b:Int) -> Int{
var c = 5
func addAll() -> Int{
return a + b + c
}
return addAll()
}
print(sum(1, 2))//1+2+5=8,所以结果为8
声明在函数内容的addAll是没有参数的,但是可以访问到sum函数里传入的参数与内容定义的变量。函数变量的作用域只会在函数内部,我们在外部去访问函数内部定义的c就会报错。这和大部分语言的特性差不多的。
3、函数多个返回值
swift和GO语言一样支持多个返回值,而swift使用元组的方式来实现的。
func muFunc(_ x: Int) -> (Int,Int) {
return (x+1,x-1)
}
var a:Int,b:Int//定义2个变量来接收返回值
(a,b) = muFunc(8)
print(a,b)//9 7
var ab = muFunc(6)//返回给元组
print(ab)//(7, 5)
4、深入学习Void
在最上面的示例写入了一个无参数无返回值的函数:welcome(),实际上没有显式返回式的函数其实还是有返回值的,也就是Void。按住键盘上的command点击Viod跳转到定义可以看到:public typealias Void = (),()是类别名,也就是说Void是一个空元组。通过对Viod的理解我们可以把下面的函数理解是同一个函数:
func welcome(){}//程序员常的
func welcome() -> Void{}//编辑器自己加的
func welcome() -> (){}//底程实现的
5、将变量声明为函数类型
swift也可以将变量声明为函数函数类型。规则及代码演示如下:
func sum(_ i: Int, _ j: Int) -> Int {
return i + j
}
var sumVar: (Int, Int) -> Int = sum
print("输出结果: " + String(sumVar(5, 6)))//11
6、函数类型作为参数类型、函数类型作为返回类型
同时函数也可以做为参数带入到其它函数里使用,也可以做为其它函数的返回值:
func sum(_ i: Int, _ j: Int) -> Int {
return i + j
}
var sumVar: (Int, Int) -> Int = sum
func printSum(sumVar: (Int, Int) -> Int,i : Int , j : Int){
print("输出结果: " + String(sumVar(i, j)))
}
printSum(sumVar:sum,i:5,j:6)//11
每个语言的函数闭包理解起来都会有一点伤脑子,所以单独罗列出来解释。因为很多时候我都需要闭包帮我们处理逻辑事务。
swfift的闭包是为了完成特定任务分享出来的功能组,上面学习的函数嵌套是可理解为有名字的闭包,是闭包的特殊情况,下面我们要学习的是使用匿名函数访问父函数里的值,闭包与函数不同的地方在于其语法更加紧凑、轻量。
1、逐步理解闭包
在swift里闭包的经典实现就是对数组的排序,首面我们使用函数实现排序转为闭包方式。
let numbers = [11,22,99,44,55,88,77,66,33]//准备一个待排列的数组
//定义一个从大到小排序规则的函数
func orderBydDesc(_ i:Int,_ j:Int) -> Bool{
return i > j
}
let num = numbers.sorted(by:orderBydDesc)//使用orderBydDescc规则对数组排序
print(num)//[99, 88, 77, 66, 55, 44, 33, 22, 11]
下面我们可以闭包实现从小到大的排序:
let numbers = [11,22,99,44,55,88,77,66,33]//准备一个待排列的数组
let num = numbers.sorted(by:{(i:Int,j:Int) -> Bool in
return i < j
})//使用闭包实现从小到大的排序
print(num)//[11, 22, 33, 44, 55, 66, 77, 88, 99]
2、闭包的语法
从上面的代码里我们就可以看到闭包的语法只多了一个in。语法结构如下:
//中文解释
{(参数) -> 返回类型 in
//逻辑代码
}
//英文解释
{(parameters) -> return type in
//code
}
//上面例子代码剥离
{(i:Int,j:Int) -> Bool in
return i < j
}
闭包表达式是写在({})花括号里的紧跟左花括号的圆括号里是闭包的参数,闭包的返回值是在参数后面和函数一样的格式,和常规的语法一样,关键字in用于分隔闭包的参数。
3、简化闭包
闭包可以利用swift的类型推导来进一步的简化闭包。上面的代码改进如下:
let num = numbers.sorted(by:{i , j in i < j})//闭包简化写法
上面代码共改了3处,首先移除了返回值和类型信息,因为编译器知道检查i < j是否成立会返回布尔值。
其次,把整个闭包表达式改为了1行。
最后,移除了关键字return,不是所有闭包都可以省略return,这里可以是因为只有一个表达式( i < j ),如果存在更多表达式,那么显式的return就是必须的。
上面的代码够简洁了吧,但还是有进一步的优化空间,这也得力于swift的个性吧,它提供了快捷参数名,可以在内联包表达式中引用,第一个参数以$0表示,第2个参数以$1以此类推,第3个就是$2..........
所以这意味着不需要给参数命名就能直接访问。
let num = numbers.sorted(by:{$0 < $1})//快捷参数
果然每一种编辑语言都会给新学编程的人一顿毒打,swift也不例外。。。。看了上面的代码是不是觉得越来越晕了。。。。
下面开始抽筋拨骨,因为这并不是最简化的写法。。。。。
如果闭包是一个函数的最后一个参数传递的,那么它就可以在函数的圆括号以外内联,因为sorted(by:)只接受一个参数,所以根本不需要圆括号,代码如下:
let num = numbers.sorted{$0 < $1}//省略圆括号的快捷参数
这种尾部闭包的语法对于包体很长的情况特别有用,在这里,尾部闭包只让我们少输入2个圆括号,从上面的语法精简就可以知道苹果把手机的拨号健取消、耳机口取消、HOME键取消,现在充电器和耳机也取消了。我都怀疑后面会不会取消手机。。。。也许这就是“简洁是智慧的灵魂”最好的诠释吧!
到这里也话你认为代码应该减少到极致了吧,但并不是。因为还有更精简的方式。。。
let num = numbers.sorted(by: <)//呵呵括号又回来了,但代码却少了
为了更好的理解swift的闭包,下面更写一些关于闭包的用法,以供理解。今后在看人家代码的时候才不会觉得原来还可以这样用。。。。
let siteName = { print("55mx.com 网络人。") }
siteName()//利用闭包打印:55mx.com 网络人。
4、高阶函数
上面代码里的sorted就是高阶函数之一,高阶函数至少接受一个函数作为参数输入,下面再来看看经常会使用到的其它3个高阶函数:
a.map(_:) 用来改变数组的值内容。
let numbers = [11,22,99,44,55,88,77,66,33]//准备一个待排列的数组
let num = numbers.map{
(s:Int) -> Int in
return s + 1 //让数组里的每个值都+1
}
print(num)//[12, 23, 100, 45, 56, 89, 78, 67, 34]
b.fillter(_:) 按条件过滤数组里的值
let numbers = [11,22,99,44,55,88,77,66,33]//准备一个待排列的数组
let num = numbers.filter{
(s:Int) -> Bool in
return s > 30 //过滤掉小于30的值
}
print(num)//[99, 44, 55, 88, 77, 66, 33]
c.reduce(_:_:) 将数组里的值按条件组合成1个值
let zhi = ["我","是","张","三"]//准备一个单个字的数组
let ju = zhi.reduce("前缀:"){
(i:String,j:String) -> String in
return i + j //将数组组合成一句话
}
print(ju)//前缀:我是张三
reduce除了拼接字符,也可以做运算,比如计算数组里所有值的和,前缀做为一个附加值0即可。
reduce(_:_:) 第一个参数是开始累加的初始值(上面为“前缀”),第二个参数是一个闭包,定义了合并数组值的规则。上面语句使用了闭包尾部语法,也可以使用闭包标准语法去写。
有时候代码运行不符合预期的时候(特别是DeBUG)我们需要对代码进行断言与拦截。
1、断言(assert)的用法
assert可以帮助开发者比较容易的发现和定位错误,一个断言断定条件是true.通过声明一个断言来确保某个必要的条件是满足的,以便继续执行接下来的代码。如果条件满足了,那么代码像往常一样执行,如果不满足了,代码就停止执行了,应用也随之停下来了。
assert(true, "条件成立程序终止!")//强制结束程序,并打印相关信息:assertion failed: 条件成立程序终止!: file /...
let a = 3
for i in 0...a{
assert(i > a, "程序运行异常!")
}
2、拦截(guard)的用法
guard用于函数里的判断拦截作用,如果条件值为false则执行guard代码块内的语句。如果条件值为true,不执行guard代码块内的语句。
guard 条件(bool) else {
//必须包含一个控制语句:return,break,continue或throw。
}
guard大部分时候用于减少if...else语句,guard条件可以有多个使用英文逗号隔开即可
//传统处理方式
func login(login:login){
if let userName = login.userNameOK {
if let password = login.passwordOK {
// 登录处理
} else {
fatalError("login wrong")
}
} else {
fatalError("login wrong")
}
}
//使用guard处理方式
func login(login:login){
guard let userName = login.userNameOK,let password = login.passwordOK,else {
fatalError("login wrong")
}
// 登录处理
}
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/101
《【基础篇】3 swift函数与闭包的使用详解》的网友评论(0)