Swift系列7-闭包

闭包

闭包是可以在你的代码中被传递和引用的功能性独立代码块.
闭包又被称为待执行的代码块.
有返回值,有形参,使用in关键字,还有@escaping关键字.
样式:

1
2
3
{(形参1,形参2,形参3) ->返回值 in  
待执行代码
}

例子:

1
2
3
4
5
let b1 = {(s1:String) ->Void in
print(s1)
}
//调用
b1("s1")

闭包的使用

尾随闭包

作为函数参数,在当前函数进行返回,这时闭包的形参会被作为返回值,书写形参时只要书写对应的类型即可;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//书写类
class Message: NSObject {
func interfaceLogin(_ s1:String,_ pa:Dictionary<String,String>,_ cl:(Dictionary<String,Any>,Int) ->Void) {
//cl表示闭包形参,类型是字典和整型
cl(["c1":100],200)
}
}
//调用类
class ClosureView: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
let msg = Message.init()
//作为函数的形参
msg.interfaceLogin("s1", ["1":"2"]) { (result, code) in
//赋值形参去接收对应的数据
print(result,code) //结果 ["c1":100],200
}
}
}

如果闭包cl是在函数返回之后调用的,我们就说这个闭包逃逸了,比如异步函数,那么需要补充@escaping关键字修饰,表示这闭包是允许逃逸的;
函数在启动任务之后返回,但是闭包要直到任务完成 – 闭包需要逃逸,以便稍后调用.

1
2
3
4
5
6
7
8
class Message: NSObject {
func interfaceLogin(_ s1:String,_ pa:Dictionary<String,String>,_ cl: @escaping (Dictionary<String,Any>,Int) ->Void) {
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 2.0) {
print("2秒之后执行")
cl(["c1":100],200)
}
}
}

结合typealias使用

结合typealias来使用的好处是,你不必在函数后面就返回该闭包,而是可以在类的任何地方返回.

第一步:定义闭包别名

1
2
typealias mineClosure = (URL,Dictionary<String, Any>) ->Void
//写形参和返回值时:只需要写对应的类型即可

第二步:定义闭包变量属性

1
var c1:mineClosure?

第三步:定义触发闭包回调方法

1
2
3
4
func getTheMessage(temp:@escaping mineClosure) {
//单独作为形参时,需要用@escaping来修饰,表示这个是逃逸闭包:因为他是在函数返回之后调用的;
self.c1 = temp
}

第四步:返回闭包

1
2
3
4
5
func begin(){
if self.c1 != nil {//判断是否实现了闭包
self.c1!(URL.init(string: "gameURL")!,["message":"NO"])
}
}

最后,调用

1
2
3
4
5
6
7
8
9
10
class ClosureView: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
let msg = Message.init()
msg.getTheMessage { (url, dic) in
print(url,dic)//赋值形参去接收对应的数据
}
msg.begin()
}
}

防止闭包循环引用

在闭包里面的对象会被闭包强引用,所以使用的时候要注意是否会引起循环引用.
下面是防止循环引用的解决方案;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//方案1,使用weak
weak var weakSelf = self
msg.interfaceLogin("d", ["d":"c"]) { (r1, c1) in
weakSelf?.result = r1
}

//方案2 [weak self]
msg.interfaceLogin("come", ["i":"j"]) { [weak self](r2, c2) in
self?.result = r2
}

//方案3 [unowned self]
msg.interfaceLogin("come", ["i":"j"]) { [unowned self](r2, c2) in
self.result = r2
}

The end