从编写面向过程语言的C语言开始就一直离不开函数,当然任何语言都有函数这个概念,函数是用来完成特定任务的独立的代码块。Swift是面相对象的语言,充满现代的编程气息,更显高级,下面看看苹果在Swift中对函数都有哪些高级应用。
函数示例
func sayHelloTo(name:String?) -> String {
return "Hello, " + (name ?? "sunfusheng")
}
print(sayHelloTo("Swift"))
print(sayHelloTo(nil))
// 输出
Hello, Swift
Hello, sunfusheng
可以提炼如下Swift函数的语法:
func 函数名(参数列表) -> 返回值类型 {
// do something ...
}
函数名没什么好讲的,不过苹果在OC中比较推崇具有语意的函数名,所以每个系统的函数名字都比较长,虽然在Swift中苹果有所收敛,但很多依然过长,不过反过来讲这样我们在读代码的时候会比较自然,有种一气呵成的感觉,比如上面的函数 sayHelloTo 加入一个介词 To,代码读起来就会很自然,关于函数名尽量学习官方的命名就好。接下来我分别从参数列表和返回值记录Swift语言的函数操作。
PS:
在 sayHelloTo 这个函数中还有 "??" 两个问号操作符,这个鬼在官方文档中也有说明,我称之为可选型的聚合操作符,看一下官方文档
Nil Coalescing Operator
let c = a != nil ? a! : b
这不就是三目运算符,通过聚合操作符可以简写如下样式:
let c = a ?? b
解释一下上述这行代码,意思就是 c 的值是 a 或 b 中一个的值,但有前提条件,就是当 a 解包后值不为 nil 时,那么就将 a 解包后的值赋值给 c,如果 a 解包后值为 nil,那么就将 b 的值赋值给c,还有一个条件就是,b 的类型必须和 a 解包后的类型一致。
函数的参数
看几个简单的使用示例
// 1.无参数函数
func sayHello() -> String {
return "Hello, sunfusheng"
}
// 2.多参数函数
func sayHelloTo(name:String, separator:String, terminator:String) -> String {
return "Hello" + separator + name + terminator
}
print(sayHelloTo("sunfusheng", separator: ",", terminator: "!"))
// 输出
Hello,sunfusheng!
// 3.可变参数函数
func sayHelloTo(names:String?..., separator:String?) -> String {
var persons:String = ""
for name in names {
persons += separator ?? ","
persons += name ?? "SunFusheng"
}
return "Hello" + persons
}
print(sayHelloTo("ZhangSan", "LiSi", nil, separator: ","))
// 输出
Hello,ZhangSan,LiSi,SunFusheng
// 4.默认参数函数,使用 "=" 赋上一个默认值
func sayHelloTo(name:String = "sunfusheng") -> String {
return "Hello, " + name
}
print(sayHelloTo())
print(sayHelloTo("sun"))
// 输出
Hello, sunfusheng
Hello, sun
如果说上面这四种情况还感觉不出 Swift 函数的牛逼,那么继续往下看!
// 5.内部参数:name
func sayHello(name:String) -> String {
return "Hello, " + name
}
// 6.外部参数:to 和内部参数:name
func sayHello(to name:String) -> String {
return "Hello, " + name
}
sayHello("Swift")
sayHello(to: "Swift")
在同一个文件中函数(5)和函数(6)是可以编译通过的,从而知道函数(5)和函数(6)是两个函数;函数(5)的函数名称:sayHello(_:),而函数(6)的名称:sayHello(to:)。当然在 Swift 中函数中第一个参数的外部参数是省略的,所以我这个函数(6)这样写是违背苹果 Swift 语言的默认风格的,当然是不提倡的。不过你再想想,函数(6)加上外部参数"to"这个介词后,对于这个函数的语意是有意义的,虽有点牵强,但辩证的看问题总是好的嘛。
这段说明中引出一个屌屌的符号 "_",下面用一下这个符号,比如下面的例子:
// 功能就是两个整数相加
func add(a:Int, b:Int) -> Int {
return a + b
}
add(1, b:1)
// 这!这么用!挺反人类的!加上外部参数呢?
func add(a:Int, and b:Int) -> Int {
return a + b
}
add(1, and: 1)
// 7.还是反人类的用法!好!使用 "_" 去掉内部参数吧!
func add(a:Int, _ b:Int) -> Int {
return a + b
}
add(1, 1)
最后,我们看看如何修改函数传入的参数,在Swift中如果想修改传入的参数值,使用关键字 inout(输入输出参数),需要注意的是:输入输出参数不能有默认值,而且可变参数不能用 inout 标记。
// 编译错误,因为函数的参数默认是常量,不能修改
func changeNum(num:Int) {
num = num * 10
}
// 编译通过,但不能修改传入的参数值
func changeNum(var num:Int) {
num = num * 10
}
// 8.使用 inout 标记修改传入的参数值
func changeNum(var num:Int) {
num = num * 10
}
var num:Int = 1
print("Before num:", num)
// 调用函数,使用取地址符传入参数的地址
changeNum(&num)
print("After num:", num)
// 输出
Before num: 1
After num: 10
上面使用了八个小例子记录并说明函数参数的使用,再看看函数返回值的使用。
函数的返回值
// 1.没有返回值的函数
func sayHello(name:String) {
print(name)
}
// 2.返回值是可选型类型
func say(content:String?) -> String? {
guard content != nil else {
return nil
}
return content
}
print(say(nil))
print(say("sunfusheng.com"))
// 输出
nil
Optional("sunfusheng.com")
// 3.返回值是元祖类型
func swap(a:Int, _ b:Int) -> (Int, Int) {
return (b, a)
}
print(swap(1, 2))
// 4.返回值是元祖类型的可选型,为方便解包后有语意加入元祖分量名称
func findMaxMinNum(arr:[Int]) -> (max:Int, min:Int)? {
guard !arr.isEmpty else {
return nil
}
var maxValue = arr[0]
var minValue = arr[0]
for num in arr {
maxValue = max(maxValue , num)
minValue = min(minValue , num)
}
return (maxValue, minValue)
}
var mm = findMaxMinNum([10, 20, 30, 40])
if let mm = mm {
print("Max:", mm.max)
print("Min:", mm.min)
}
// 输出
Max: 40
Min: 10
Swift 函数的基本用法先记录到此,越学越觉得 Swift 屌屌的!下一篇聊聊 Swift 和 Java 的函数式编程。
Swift 学习笔记将持续更新,欢迎关注我的公众号,大家加油!