Swift学习笔记(结合代码,实践Tips)--Day2
importUIKit
varstr ="Hello, playground"
//复习函数
//练习,写一个求平均数的函数
funcgetAverage (scores:[Int]) ->CGFloat{
varsum:CGFloat=0
forscinscores{
sum +=CGFloat(sc)
}
returnsum /CGFloat(scores.count)
}
getAverage([1,2,3,4,5])
/*
*
*1.函数可以带有可变个数的参数,这些参数在函数内表现为数组的形式:这样写也行
*/
funcsumOf(numbers:Int...) ->Int{
varsum =0;
foriteminnumbers{
sum += item
}
returnsum
}
sumOf(2,4,5,6)
//函数可以嵌套。被嵌套的函数可以访问外侧函数的变量,你可以使用嵌套函数来重构一个太长或者太复杂的函数。
funcsum(scores:Int...) ->Int{
varss =0;
foriteminscores{
ss += item
}
returnaverage(ss, scores.count)
}
funcaverage(number:Int, count:Int) ->Int{
returnnumber / count
}
varave =sum(1,2,3,4,5)
//函数是第一等类型,这意味着函数可以作为另一个函数的返回值。上面的demo其实已经证明了,average不就是第一个函数的返回值了么
funcmakeIncrementer() -> (Int->Int) {
funcaddOne(number:Int) ->Int{
return1+ number
}
returnaddOne
}
varincrement =makeIncrementer()
increment(7)
//函数也可以当做参数传入另一个函数,这个是我最喜欢的,在OC里面经常用的
//在下面这个函数的demo中,其实是将第一个小函数当做实参传入到了第二个大函数中,第二个大函数中存在一个参数类型和返回类型和小函数的形参来接收,实际上就是另外一个小函数,我是这样理解的,个人习惯不一样,只要能记得这个语法就好我觉得
funclessThan(number:Int) ->Bool{
returnnumber <10
}
funchasMatch(list:[Int],condition:Int->Bool) ->Bool{
foriteminlist{
ifcondition(item){
returntrue
}else{
returnfalse
}
}
returntrue
}
varnumbers = [20,9,12,7]
hasMatch(numbers,lessThan)
//再写一个玩玩//第一个函数不会计算平均数,得依靠传过来的一个函数计算,这个函数会计算
funcMeGetAverage(items:[Int],myMethod:(Int,Int)->Int) ->Int{
varsum =0
foriteminitems{
sum += item
}
returnmyMethod(sum,items.count)
}
funcgetAverage(sum:Int,count:Int)->Int{
returnsum / count
}
varnumbers1 = [1,2,3,4,5]
MeGetAverage(numbers1,getAverage)
/**
*2.闭包
*函数实际上是一种特殊的闭包,你可以使用{}来创建一个匿名闭包。使用in将参数和返回值类型声明与闭包函数体进行分离。
*/
//具体没咋看懂啊
//numbers.map({
//(number: Int) -> Int in
//let result = 3 * number
//return result
//})
//let mappedNumbers = numbers.map({ number in 3 * number })
//mappedNumbers
//关于闭包网上找到的好像是能讲解的知识点
/**
*
闭包有三种形式:
1.全局函数是一个有名字但不会捕获任何值的闭包。
2.嵌套函数是一个有名字并可以捕获到其封闭函数域内的值的闭包。
3.闭包表达式是一个利用轻量级语法所写的,可以捕获其上下文中变量或常量值的匿名闭包。
今天,我们要讨论的是第三种形式,尤其讨论它是如何将繁复的、可读性比较差的业务逻辑代码压缩成高可读性、简明明了的形式。
大家还记得数组的map方法么?它的参数就是一个闭包,它会将数组里的每一个元素放在闭包中进行处理,然后返回一个新的数组,甚至是与原数组不同元素类型的新数组。
*/
numbers.map({
(number:Int) ->Intin
letresult =3* number
returnresult
})
letmappedNumbers =numbers.map({ numberin3* number })
//练习重写闭包,对所有奇数返回0。在if语句中,条件必须是一个布尔表达式
vararr1 =numbers
vararr2 =arr1.map({ (item:Int) ->Intin
ifitem %2!=1{//偶数
returnitem
}else{//奇数
return0
}
})
print(arr1)
print(arr2)
/**
*靠这个我好像懂得了闭包网页地址:http://www.tuicool.com/articles/faYbmy
*用一个例子来说明。今天我办生日聚会,要迎接很多人,并且为每个人都准备了一句欢迎词。我们要怎么做呢?首先我们将迎接的人放进一个数组名叫guestList,然后用一个名叫greetPeople的函数为每个人生成欢迎词:
func greetPeople(person: String) -> String
{
return "Hello, \(person)!"
}
let guestList = ["Chris", "Jill", "Tim"]
let fullGreetings = guestList.map(greetPeople)
然后将greetPeople函数作为guestList数组的map函数的参数传入,并返回一个新的数组fullGreetings,这个数组就包含了每个人的欢迎词。
如果我们想展示一下每个人的欢迎词,我们甚至可以这样写:
fullGreetings.map(println)
这时也许有人要质疑了,println函数不是没有返回值么?那么map函数会返回什么呢?其实每一个没有返回值的函数,都会返回一个空的元组(tuple),所以说上述代码的返回值其实是Array<()>。
上面的例子中我们就是将一个全局函数greetPeople作为一个闭包来使用的。
简明扼要的闭包表达式
其实Swift已经为我们提供了很多简化的语法,可以让我们保证代码的高可读性和维护性。还用上面的例子来说明,对于greetPeople这个全局函数来说,其实只需要使用一次,所以我们没必要单独定义这个函数。我们可以直接使用闭包表达式来处理:
let fullGreetings = guestList.map({(person: String) -> String in return "Hello, \(person)!"})
闭包表达式其实是函数的字面值,官方一般称之为匿名函数。一般当我们需要使用函数快速的实现一个简短的处理逻辑并且只使用一次的时候,我们可以省去函数名,使用简化的语法。上面的代码中可以看到关键字in之前是闭包表达式的参数和返回值,in之后是闭包表达式实际处理逻辑的代码区域。
下面我们将使用Swift更多的特性来进一步简化闭包表达式。
我们知道Swift中有类型推断的特性,所以我们可以取掉参数类型:
let fullGreetings = guestList.map({(person) -> String in return "Hello, \(person)!" })
像我们示例中的这种单一闭包表达式,编译器可以根据in之前的返回值类型和return之后的返回数据类型自动判断,所以我们可以省略返回值和return关键字:
let fullGreetings = guestList.map({person in "Hello, \(person)!" })
其实在Swift中还提供了参数的简写方式:$0代表第一个参数、$1代表第二个参数以此类推。所以我们又可以将参数名称省略:
let fullGreetings = guestList.map({ "Hello, \($0)!" })
当函数的最后一个参数是闭包时,可以将闭包写在()之外,这也是Swift的一个特性,所以我们还可以继续简化:
let fullGreetings = guestList.map(){ "Hello, \($0)!" }
当函数有且仅有一个参数,并该参数是闭包时,不但可以将闭包写在()外,还可以省略():
let fullGreetings = guestList.map{ "Hello, \($0)!" }
到目前为止,示例中的闭包表达式已经被我们根据Swift的特性,简化为简明扼要、高可读性的闭包表达式了,是不是很酷呢!
参考原文:Closure Expressions in Swift
*/