swift学习日记(三) 函数 闭包

好像基础语法看一两个钟就可以了。。。跟其它语言相比没什么太大差别,下面的内容将相对要难一点了


一,函数

相对来说,函数可能是差别挺大的一个了


1,基本形式

func printf(str:String)->Int {
    print(str)
    return 0
}
printf("hello world")

 swift有点像弱类型和强类型的结合体,func声明一个函数,在后面用->声明返回类型,参数里跟变量的声明类似,然后是函数体,返回值跟c一样 

多参、无参、无返回值跟c一样

多参有点例外,这是在实践的时候发现的,在函数调用时,如果有多个参数,那么从第二个参数要加上label,比如:

func printf(a1:Int, b1:Int, c1:Int) {
    print("a:\(a), b:\(b), c:\(c1)")
}

printf(a, b1: b, c1: c)

不要问为什么,苹果就是这么规定的,有点诡异都好,也只能记住了

写这篇博客的时候我没发现的,后来自己练的时候,报了这么一个错: missing argument label: "c1" in call  查了查才发现这个问题

2,多返回值

怎么实现多返回值一直都是c/c++的麻烦之处,swift就很方便了,返回类型改成元组即可,有写过之前循环中的元组的应用的话应该很容易接受

func printf(str:String)->(Int, String) {
    print(str)
    return (0, "successful")
}
print(printf("hello world"))

此外,还可以在返回值中声明元组中每一项的名称,这样就可以返回值中这么用


func printf(str:String)->(num:Int, info:String) {
    print(str)
    return (0, "successful")
}
let ret = printf("hello world")
print("\(ret.num) \(ret.info)")


3,外部参数

swift有个非常贴心的特性,先看代码

func printf(bla str:String)->(num:Int, info:String) {
    print(str)
    return (0, "successful")
}
let ret = printf(bla: "hello world")
print("\(ret.num) \(ret.info)")

一般来说,我们在调用函数的时候,都是需要知道每个参数的意义,也就是说使用者更需要知道参数的变量名,然而大多数语言中,只有函数的定义里才有每个参数的变量名

所以swift就添加了个外部参数的特性,如上,这样在xcode里,调用该函数时,编译器会帮你补上调用者定义的外部参数名


有一点需要注意的是,如果使用了外部参数名,那在调用时就必须带上外部参数名,否则报错


4,参数默认值

这个跟c是一样的,就不说了,直接贴代码

func printf(str str:String = "blabla")->(num:Int, info:String) {
    print(str)
    return (0, "successful")
}
let ret = printf()
print("\(ret.num) \(ret.info)")

5,可变参数

有时候函数调用的参数数量不确定,于是swift提供了个可变参数,如下,语法就是"..."

func arithmeticMean(numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers

不过这个可变参数没你想得那么智能,它有很多限制

首先是一个函数只能有一个可变参数,可变参数必须放在参数列表最后

然后是这个可变参数会被解释成一个相同类型的常量数组,如代码中的numbers会包含所有参数。

如果函数有一个或多个参数使用默认值,并且还具有可变参数,将可变参数放在列表的最末尾的所有默认值的参数之后。

这很好用,但没那么好用


6,变量参量

swift默认所有参数都是let常量,也就是说不给改,想使用变量参量的话,前面加个var即可,如果有外部参数,则加在外部参数前

func printf(id:Int, var bla str:String = "blabla")->(num:Int, info:String) {
    print(str)
    str = ""
    return (0, "successful")
}
let ret = printf(0)
print("\(ret.num) \(ret.info)")
需要注意的是,如果在函数内没有改变参数的值,xcode会给出warning,建议改成let类型


7,函数类型


这是个很有趣的特性

在swift中,函数本身也是一种数据类型

var mathFunction: (Int, Int) -> Int = addTwoInts
也就是说,函数名本身也是一个变量

这就带来一个很有趣的用法

func fun(inc:(Int, Int)->Int)->Int {
    return 0
}

我们就可以在一个函数里直接调用另一个函数了,这可比c++11中的函数指针要好用得多了

再给一个例子,更加地直观

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8"


8,嵌套函数

swift允许嵌套函数,注意作用域即可


9,输入输出参数


这个问题和c++是一样的,函数是有作用域的,函数的参数做出的改变不能在函数外体现


如果想要一个函数可以修改参数的值,并且这些修改在函数结束调用后仍然存在,那就可以定义为输入输出参数,在参数前面添加inout关键字,这个值被函数修改后被传出函数,并替换原来的值,同时,传入的只能是变量而不能是常量,当传入的参数作为作为输入输出参数时,需要在参数面前加 & 符号,表示这个值可以被修改

func swapTwoInts(inout a: Int, inout b: Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"


二,闭包


闭包简单来说就是 {}中间的代码,这个概念本身不难

1,

闭包最大的作用是简化一些函数的写法


有时候我们需要写一个函数,但是函数功能实际上只有一行,并且也只用一次,这时候我们就可以改成闭包形式


比如

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sort(names, backwards)

我们可以这么写,这种写法实际上可以看作是一种匿名函数

var reversed = sort(names, { (s1: String, s2: String) -> Bool in
return s1 > s2
})

函数改写成闭包,形式上来说就是在 {}内 加上 () -> in,in后面接上函数内的代码即可,很好理解


事实上闭包形式还可以写成更简单的形式,比如

reversed = sort(names, { s1, s2 in return s1 > s2 } )
reversed = sort(names, { s1, s2 in s1 > s2 } )

reversed = sort(names, { $0 > $1 } )
reversed = sort(names, >)

颤抖吧,地球人


注:在swift2中,sort一改成sorted


2,trailing闭包

先把代码贴这里

let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
// strings is inferred to be of type String[]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]

 map是数组的一个方法,其接受一个函数,会将数组中每一个值按你的规则转化 

这段代码要看的话还是可以理解的,只是要自己写的话,呵呵

3,获取值

还是贴代码吧,这些代码都太漂亮了,初学者能看懂就不错了,要自己写还是得慢慢练

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()

 swift另一个很吊的地方在于,makeIncrementor返回一个函数,但这个函数是在其函数体内定义的,并且会使用函数体内的变量 

不过感觉这个跟闭包好像关系不是很大



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值