swift block
Posted 博BOBO
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift block相关的知识,希望对你有一定的参考价值。
-
block闭包表达式
在 swift中可以用 func 定义一个函数,也可以用闭包表达式定义一个函数
func sum(v1:Int, v2:Int) -> Int v1 + v2
let sum2 = (v1:Int, v2:Int) -> Int in
return v1 + v2
sum(v1: 10, v2: 20)//func定义的函数
sum2(10, 20)//闭包表达式定义的函数
func sun(param1:Int, param2:Int, test:( Int, Int) -> Int)
print(test(param1, param2))
sun(param1:20 , param2:20, test:
(v1:Int, v2:Int) -> Int in
return v1 + v2
)
//闭包表达式简写
sun(param1:20 , param2:20, test:
v1, v2 -> Int in
return v1 + v2
)
sun(param1:20 , param2:20, test:
v1, v2 in
return v1 + v2
)
//闭包表达式隐式返回
sun(param1:20 , param2:20, test:
v1, v2 in v1 + v2
)
//参数名称简写
sun(param1:20 , param2:20, test:
$0 + $1
)
//函数式闭包
sun(param1: 2, param2: 3, test: +)
-
尾随闭包
最后一个参数是闭包表达式的时候,可以独立于前面的参数,写在函数参数外面的闭包表达式,使结构看起来再加清晰整洁,属于结构优化,默认闭包表达式作为参数的时候采用尾随闭包的形式。
sun(param1: 12, param2: 13) (v1:Int, v2:Int) -> Int in
return v1 + v2
//尾随闭包表达式
sun(param1: 12, param2: 13) v1, v2 in
v1 + v2
//尾随闭包表达式简写
sun(param1: 20, param2: 12) return $0 + $1
//尾随闭包表达式简写
sun(param1: 10, param2: 12) $0 + $1
sun(param1: 10, param2: 12) $0 + $1
sun(param1: 2, param2: 3, test: +)
-
自动闭包
顾名思义根据传入的参数,自动生成闭包;延迟执行,属于性能优化,除些之外也属于结构优化,调用者无需关心参数类型,用@autoclosure 修饰。
@autoclosure 只支持()->T 的格式参数,并且不仅仅只支持最后一个参数。
系统的合并运算符??属于自动闭包。
自动闭包允许你延迟处理,因此闭包内部的代码直到你调用它的时候才会运行。
//添加 @autoclosure 关键字, 当闭包被调用的时候,会返回被包装在其中的表达式的值
public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
if !condition()
print(message())
let number = 3
assert(number > 3, "number 不大于3") //输出: number 不大于3
//自动闭包允许延迟处理
var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
print(person.count) // 输出: 4
let deletePerson = person.remove(at: 0)
print(person.count) //此时输出还是 4,因为没有调用闭包没有被调用,闭包里的代码没有被执行
//此时调用闭包
print(deletePerson()) //输出 "zhangsan"
print(person.count) //输出: 3
//闭包作为实际参数传递给函数时,能获得同样的延时求值行为
//闭包作为实参, 可以显示的使用闭包
var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
func serve(customer customerProvider: () -> String)
print("Now serving \\(customerProvider())!")
//函数接受一个返回顾客名字的显式的闭包
serve(customer: person.remove(at: 0) ) //打印: Now serving zhangsan!
//自动闭包作为实际参数
var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
//customerProvider 参数将自动转化为一个闭包,因为该参数被标记了 @autoclosure 特性
func serve(customer customerProvider: @autoclosure () -> String)
print("Now serving \\(customerProvider())!")
serve(customer: person.remove(at: 0)) //打印: Now serving zhangsan!
-
自动+逃逸
//自动闭包允许逃逸,同时使用 @autoclosure 和 @escaping 标志
var customerInLine = ["zhangsan", "lisi", "wangwu", "zhaoliu"]
var customerProviders: [() -> String] = []
func collectionCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String)
customerProviders.append(customerProvider)
print(customerProviders.count) //打印: 0
collectionCustomerProviders(customerInLine.remove(at: 0))
collectionCustomerProviders(customerInLine.remove(at: 0))
print(customerInLine.count) //打印: 4
print(customerProviders.count) //打印: 2
for c in customerProviders
print("Now serving \\(c())")
/*
Now serving zhangsan
Now serving lisi
*/
collectCustomerProviders(_ : ) 函数并没有调用传入的 customerProvider 闭包,而是将闭包追加到了 customerProviders 数组中。
这个数组定义在函数作用域范围外,这意味着数组内的闭包能够在函数返回之后被调用。
因此,customerProvider 参数必须允许“逃逸”出函数作用域。
-
swift 闭包值捕获
- 闭包可以对外部函数的变量、常量进行捕获;
- 闭包捕获时机是在函数执行完,return 时再去捕获
- 当函数里有多个闭包时,只会对变量、常量捕获一次,多个闭包对捕获的变量、常量共享
- 闭包不会对全局变量进行捕获
闭包可以在其被定义的上下文中捕获常量或者变量。即是定义这些常量和变量的原作用域已经不存在了,闭包仍然可以在闭包函数体内引用和修改这些值。
-
闭包类型
和类一样,闭包也是引用类型
-
闭包
闭包和闭包表达式并不一是一个东西,半包表达式是函数的另外一种定义,而闭包是一个函数和它所捕获变量/常量环境的组合;
一般指定义在函数内部的函数;一般它捕获的是外层函数的局部变量/常量;
闭包和和闭包表达式的区别?
闭包表达式是:函数的另外一种表现形式,为了实现简介和高效,有不同的表现形式,例如自动闭包,尾随闭包;
闭包是:封装在函数中的函数或者闭包表达式,且捕获了局部变量的运行环境。它运用了闭包表达式,但闭包表达式不是闭包。
-
循环引用的问题
objective-c解决闭包的循环引用问题一般是先声明
__weak typedef(weakSelf) = self;
然后使用weakSelf对本类的属性调用。
swift中也有类似于objective-c中的方法:首先是声明:weak var weakSelf = self;
然后使用weakSelf对本类的属性调用。self可能会为nil,所以需要用var。 -
闭包内修改外部变量
在objective-c中,我们通常使用__block来声明一个变量,这样就可以在闭包内对这个变量进行修改。
在swift中没有__block这种关键字,但是swift中的闭包是做了优化处理,是可以直接捕获上下文中的变量。所以可以直接在闭包中对变量进行修改。
以上是关于swift block的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 Swift 的单数返回表达式中使用闭包简写变量必须详尽无遗?