Coggle requires JavaScript to display documents.
OC中的__block在Swift中叫做截获变量的引用。闭包默认会截取变量的引用,也就是说所有变量默认情况下都是加了__block修饰符的。
不管是否显示的把变量写进捕获列表,闭包都会对对象有强引用。如果闭包是某个对象的属性,而且闭包中截获了对象本身,或对象的某个属性,就会导致循环引用。这和OC中是完全一样的。解决方法是在捕获列表中把被截获的变量标记为weak或unowned。
Swift中实现Weak-Strong Dance一般有三种方法。分别是最简单的if let可选绑定、标准库的withExtendedLifetime方法和自定义的withExtendedLifetime方法。
swift4.2 networkRequest.fetchData() { [weak self] result in guard let self = self else { return } }
OC的block会截获外部变量,对于int等基本数据类型,block的内部会拷贝一份,所以生成block后再修改变量,不会影响被block截获的变量
想在block中修改被截获的基本类型变量,我们需要把它标记为__block,对于被标记了__block的变量,block在截获它时,会保存一个指针指向value
只有由__block修饰符修饰的变量,在被block截获时才是可变的
总结:简单来说,除非标记为__weak,block总是会强引用任何捕获的对象。而__block表示捕获的就是指针本身,而非另一个指向这个对象的指针。也就是说,被__block修饰的对象在block内、外的改动会互相影响。
如果想避免循环引用问题,首先要确定block引用了哪些对象,然后判断这些对象是否直接或间接持有block,如果有的话把这些对象标记为__weak避免block强引用它。
OC中实现Weak-Strong Dance一般用@weakify(self)/@strongify(self)
OC中默认截获变量,Swift默认截获变量的引用。它们都会强引用被截获的变量。
Swift中没有__block修饰符,但是多了截获列表。通过把截获的变量标记为weak避免引用循环
在使用可选类型时,要明确闭包截获了可选类型还是实例变量。这样才能正确判断是否发生循环引用。
__block与__weak
__weak只能在ARC模式下使用,也只能修饰对象,不能修饰基本数据类型;
__unsafe_unretained修饰符为SDK 4.3以前版本的__weak的替代品
在MRC中,__block 修饰,可以避免循环引用;ARC中,__block 修饰,同样会引起循环引用;
不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型;
__block对象可以在block中被重新赋值,__weak不可以; (__weak修饰符, 不能修改对象本身, 可以修改对象的属性.类似只读属性readonly)
只有由__block修饰符修饰的变量,在被block截获时才是可变的; __block会强引用变量;从原理上分析,__block修饰的变量被封装在结构体中,block内部持有对这个结构体的强引用。这一点不管是对于基本类型还是指针都是通用的
__block修饰符本质上是通过截获变量的指针来达到在闭包内修改被截获的变量的目的。
在ARC中, __block修饰的变量会引用计算增加;block内部持有的对象引用计数会增加; 防止循环引用使用__weak修饰在Block中实用的对象
在MRC中,__block修饰的变量的引用计算不变; block内部对引入的外部对象,会增加引用计数。防止循环引用使用__block修饰在Block中实用的对象