常用写法:
- OC中:
1.先用typedef声明一个block的名称
typedef void(^CallBackBlock)(int num);
@property (nonatomic, copy) CallBackBlock block;
2.直接定义一个block属性
@property (nonatomic, copy) void(^block1)(void);// 没有参数
@property (nonatomic, copy) void(^block2)(int num);
3.block的调用和实现
self.block1();
self.block1 = ^{
};
self.block2(2);
self.block2 = ^(int num) {
NSLog(@"%d", num);
};
- Swift中:
1.定义一个block属性
var finishedLoadBack : ((_: Int) -> ())?
2.作为参数的block
func requestData(URLString: String, finishedCallback: @escaping (_ result: Any) -> ())
finishedCallback(result)
}
3.block的调用和实现
if let finishedLoadBack = finishedLoadBack {
finishedLoadBack(5)
}
finishedLoadBack = {[weak self] num in
}
requestData(URLString: url_giftList) { (result) in
}
注意事项:
- block默认存储在栈中,如果对block进行copy操作,block会转移到堆中;block在栈中访问外界对象不会对对象进行retain操作,block在堆中访问外界对象会对对象进行retain操作。
- 在block中访问外界 的对象,一定要给对象加上
__block
,只要加上__block
,哪怕block是在堆中,也不会对外界的对象进行retain(在MRC中)。 - 在block中访问外界的对象,相当于是外界对象作为形参传递进来,只能访问不能修改,是值的传递;给对象加上
__block
,相当于外界对象把地址传进来,所以可以修改值。 - 用copy修饰block,是为了保存block,这样可以保住block中使用的外界对象的命,避免以后调用block时,外界对象已经释放。
解决循环引用的方法:
-
OC中:
在MRC中使用__block
,在ARC中使用__weak
-
Swift中:
block称为闭包,解决方法如下
1.weak var weakSelf : viewController? = self
tool?.loadData { (content) in
weakSelf?.view.backgroundClolor = UIColor.red
}
2.tool?.loadData { [weak self] (content) in
self?.view.backgroundClolor = UIColor.red
} // 最好使用的写法
3.tool?.loadData { [unowned self] (content) in
self.view.backgroundClolor = UIColor.red
} // 前提是self类不会被释放,否则容易造成野指针错误
__block和__weak的区别:
1.在循环引用中:
-
__block
本身并不能避免循环引用,避免循环引用需要在block内部把__block
修饰的obj置为nil -
__weak
可以避免循环引用,但是其会导致外部对象释放了之后,block内部也访问不到这个对象的问题,我们可以通过在block内部声明一个__strong
的变量来指向weakObj,使外部对象既能在block内部保持住,又能避免循环引用的问题
2.在功能上:
-
__block
会持有该对象,即使超出了该对象的作用域,该对象还是会存在的,直到block对象从堆上销毁;而__weak
仅仅是将该对象赋值给weak对象,当该对象销毁时,weak对象将指向nil; -
__block
可以让block修改局部变量,而__weak
不能。
另外,MRC中__block
是不会引起retain;但在ARC中__block
则会引起retain。所以ARC中应该使用__weak
。
网友评论