闭包的介绍
闭包和OC中的block非常相似◦OC中的block是匿名的函数
Swift中的闭包是一个特殊的函数block和闭包都经常用于回调
注意:闭包和block一样,第一次使用时可能不习惯它的语法,可以先按照使用简单的闭包,随着学习的深入,慢慢掌握其灵活的运用方法.
闭包的使用
block的用法回顾
定义网络请求的类
@interface HttpTool : NSObject
- (
void)loadRequest:(
void (^)())callBackBlock;
@end
@implementation HttpTool
- (
void)loadRequest:(
void (^)())callBackBlock
{
dispatch_async(dispatch_get_global_queue(
0,
0), ^{
NSLog(@
"加载网络数据:%@", [
NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
callBackBlock();
});
});
}
@end
进行网络请求,请求到数据后利用block进行回调
- (
void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[
self.httpTool loadRequest:^{
NSLog(@
"主线程中,将数据回调.%@", [
NSThread currentThread]);
}];
}
block写法总结:
block的写法:
类型:
返回值(^
block的名称)(
block的参数)
值:
^(参数列表) ;
使用闭包代替block
定义网络请求的类
class HttpTool: NSObject {
func loadRequest(callBack
: ()->()){
dispatch_async(dispatch_get_global_queue(
0,
0)) { () ->
Void in
print(
"加载数据", [
NSThread.currentThread()])
dispatch_async(dispatch_get_main_queue(), { () ->
Void in
callBack()
})
}
}
}
进行网络请求,请求到数据后利用闭包进行回调
override func touchesBegan(
touches: Set<UITouch>, withEvent
event: UIEvent?) {
// 网络请求
httpTool.loadRequest
({ () -> () in
print("回到主线程", NSThread.currentThread());
})
}
闭包写法总结:
闭包的写法:
类型:
(形参列表)->(返回值)
技巧:初学者定义闭包类型,直接写
()->().再填充参数和返回值
值:
{
(形参) -> 返回值类型
in
// 执行代码
}
闭包的简写
如果闭包没有参数,没有返回值.in和in之前的内容可以省略
httpTool
.loadRequest({
print(
"回到主线程", NSThread
.currentThread())
})
尾随闭包写法:
如果闭包是函数的最后一个参数,则可以将闭包写在()后面如果函数只有一个参数,并且这个参数是闭包,那么()可以不写
httpTool
.loadRequest() {
print(
"回到主线程", NSThread
.currentThread())
}
httpTool
.loadRequest {
print("回到主线程", NSThread.currentThread());
}
闭包的循环引用
如果在HttpTool中有对闭包进行强引用,则会形成循环引用补充:在Swift中检测一个对象是否销毁,可以实现对象的 deinit 函数
deinit {
print(
"ViewController----deinit")
}
循环引用的(实现)
该实现是为了产生循环引用,而产生的循环引用
class HttpTool: NSObject {
var callBack : (()
->())
?
func loadRequest(callBack : ()
->()){
dispatch_async(dispatch_get_global_queue(
0,
0)) { ()
-> Void in
print(
"加载数据",
[NSThread
.currentThread()
])
dispatch_async(dispatch_get_main_queue(), { () -> Void in
callBack()
})
}
self.callBack = callBack
}
}
swift中解决循环引用的方式
方案一:
使用weak,对当前控制器使用弱引用但是因为self可能有值也可能没有值,因此weakSelf是一个可选类型,在真正使用时可以对其强制解包(该处强制解包没有问题,因为控制器一定存在,否则无法调用所在函数)
weak var weakSelf =
self
httpTool
.loadData {
print(
"加载数据完成,更新界面:",
NSThread.currentThread())
weakSelf!
.view.backgroundColor =
UIColor.redColor()
}
方案二:
和方案一类型,只是书写方式更加简单可以写在闭包中,并且在闭包中用到的self都是弱引用
httpTool
.loadData {[weak self] () -> ()
in
print(
"加载数据完成,更新界面:", NSThread
.currentThread())
self!
.view.backgroundColor = UIColor
.redColor()
}
方案三:(常用)
使用关键字 unowned从行为上来说 unowned 更像OC中的 unsafe_unretainedunowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 “无效的” 引用,它不能是 Optional 值,也不会被指向 nil
httpTool
.loadData {[unowned self] () -> ()
in
print(
"加载数据完成,更新界面:", NSThread
.currentThread())
self
.view.backgroundColor = UIColor
.redColor()
}
转载请注明原文地址: https://ju.6miu.com/read-1124026.html