Swift闭包和函数
函数在Swift中只是一种特殊的闭包,闭包在Swift语言中是一等公民,支持闭包嵌套和闭包传递。
Swift中的闭包(Closures) 类同于于Objective-C中的代码块(Blocks) ,可以相互参照理解。
函数
//函数语法格式
()->()
定义函数
定义函数需要关键词func, 函数接受和返回的参数可以为0个,一个或多个(返回多个参数可以使用Tuple),且返回时需要使用 **-> **。
//定义函数
func bestWishes(name: String, blessing: String) -> (guest: String, messageOfCongratulation: String) {
return ("属下, \(name).", "祝教主: \(blessing) ")
}
//调用函数
let retValue = bestWishes(name: "白龙使韦小宝", blessing: "仙福永享,寿与天齐!")
print(retValue)
print(retValue.guest)
print(retValue.messageOfCongratulation)
//把以上代码粘贴到Playground中会输出以下内容:
//("属下, 白龙使韦小宝.", "祝教主: 仙福永享,寿与天齐! ")
//属下, 白龙使韦小宝.
//祝教主: 仙福永享,寿与天齐!
函数类型
每一个函数都有函数类型,该类型由函数自身参数类型和返回类型组成。
//样例
func sum(x: Int, y: Int) -> (result: Int) { return x + y }
上述函数的的类型是:
(Int, Int) -> (Int)
再来一个例子:
//开篇提到的函数
func bestWishes(name: String, blessing: String) -> (guest: String, messageOfCongratulation: String) {
return ("属下, \(name).", "祝教主: \(blessing) ")
}
//函数类型
(String, String) -> (String, String)
传递函数和返回函数
我们来实现一个函数可以返回另一个函数,这样返回的函数可以赋值给一个变量并调用它。
func eatPoison () -> ((String, Int) -> String) {
func posion(name: String, times: Int) -> (String) {
return "\(name) 服用豹胎易筋丸 \(times) 次"
}
return posion
}
let retValue = eatPoison()
print(retValue("韦小宝", 3))
//以上代码粘贴到Playground中会输出以下内容:
//韦小宝 服用豹胎易筋丸 3 次
可变参数函数
可变参数函数指的是函数拥有若干数目不定参数的函数,可以通过类数组类型去访问所有参数。
func poisonRawMaterial (materials: String...) -> () {
for material in materials {
print("\(material)")
}
}
poisonRawMaterial(materials: "豹胎", "鹿胎", "紫河车", "海狗肾")
//以上代码粘贴到Playground中会输出以下内容:
//豹胎
//鹿胎
//紫河车
//海狗肾
闭包
//闭包语法格式
{()->() in}
定义闭包
闭包一般定义在大括号内,闭包由函数类型(闭包头部) 和 关键词 in后的闭包主体组成。
{ (参数) -> 返回类型 in
闭包主体
}
var clos1 = {
() -> Void in
print("第一个闭包")
}
clos1()
通过函数 map可以把操作施加到数组所有元素上。
let murderers = ["胖头陀", "陆高轩", "瘦头陀"]
murderers.map({
(murderer: String) -> String in
"\(murderer) 已被洪教主杀死!"
})
注意:上面的闭包没有使用return关键字,因为如果闭包是单行语句闭包,单行语句计算结果会隐式地返回,return关键字可以省略。
Swift可以根据上下文推理参数和返回值类型,这样返回值类型和参数类型可以省略不写。
func applyMutliplication(value: Int, multFunction: (Int) -> Int) -> String{
return String(multFunction(value))
}
applyMutliplication(value: 4,multFunction: {value in
value * 5
})
参数名缩写 - 闭包的参数可以通过位置来访问,如($0,$1, ...)。
applyMutliplication(value: 4,multFunction: {$0 * 5})
尾随闭包 - 而如果闭包是函数的最后一个参数,闭包参数可以写在大括号外。
applyMutliplication(value: 4) {$0 * 5}
关于Swift闭包更多参看官方文档。
循环引用
在引用计数的系统中,都存在这循环引用的风险,而循环引用可能会导致内存泄漏,这令人不得不防。
在定义Swift闭包时同时定义捕获列表作为闭包的一部分,捕获列表定义了闭包体内捕获一个或者多个引用类型的规则。这时使用不当就可能引起循环引用。
跟解决两个类实例间的循环强引用一样,声明被捕获的引用为弱引用(weak)或无主引用(unowned)就可打破循环引用,至于使用弱引用还是无主引用应当根据上下文来选择。
//延迟加载, 使用unowned打破循环引用。
lazy var printName: ()->() = { [unowned self] in
print(self.name)
}
printName是 self 的属性,会被 self 持有,而它本身又在闭包内持有 self
,这就存在循环引用的风险,上面例子中用unowned打破了循环,再来使用weak关键词。
lazy var printName: ()->() = { [weak self] in
if let strongSelf = self {
print("用户名: \(strongSelf.name)")
}
}
注意在如何选择使用unowned和weak请参考下述规则:
-
如果捕获的引用绝对不会置为nil,或当闭包和捕获的实例总是互相引用时并且总能同时销毁时,可以将闭包内的捕获定义unowned。
-
当捕获引用有时可能会是nil时,将闭包内的捕获定义为weak。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil,这使我们可以在闭包内检查它们是否存在。
更多请多参看苹果官方文档。
推荐阅读
Swift 之 非逃逸闭包与逃逸闭包
更多
获取更多内容请关注微信公众号豆志昂扬:
- 直接添加公众号豆志昂扬;
- 微信扫描下图二维码;