【转】block强弱引用

原地址:Block内的强引用

  众所周知,当某个对象持有着一个Block的时候,如果在Block内部使用强引用反过来持有这个对象,就会导致引用循环。为了避免引用循环,可以使用__weak修饰符,苹果的官方文档在用代码演示__weak修饰符的时候,有这么一个例子:

  那么,myController持有着completionHander,在completionHander内部又用一个strongMyController反过来去持有myController,这不也是一个引用循环吗?为了探究这个问题,可以用下面的方法来测试一下:

1、编写一个类ViewController,然后在类内编写方法test,做一个疑似的引用循环:

2、然后通过一个clang命令将这个类转换成C语言代码:

clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -fobjc-arc -stdlib=libc++ -mmacosx-version-min=10.7 -fobjc-runtime=macosx-10.7 -Wno-deprecated-declarations ViewController.m

3、由此可以得到一个cpp文件,将文件中主要的部分提取出来如下:

4、可以发现:

(1)、在Block结构体中看到,被Block捕获的变量是

ViewController *const __weak weakSelf;

所以Block本身对self的引用仍然只是弱引用,并不造成引用循环。

(2)、strongSelf只存在于Block对应的函数__ViewController__test_block_func_0里,它的生命周期只在这个函数执行的过程中,函数执行前它不会存在,函数执行完它立刻就被释放了。

(3)、所以:

①、如果函数执行前self变为nil了,那么函数不会执行,没有任何引用循环发生;

②、如果函数执行过程中self变为nil了,那么函数一开始声明的strongSelf会暂时持有着self,此时会有一个暂时的引用循环。当函数执行完(即是Block执行完),strongSelf超出作用域被释放,引用循环从这里开始打破。接下来,由于没有任何强引用持有self了,于是self被释放,最后Block也因为没有任何强引用持有它也被释放了。所有对象就都被顺利释放了。

  所以最终可以确定:苹果的演示代码有可能会造成引用循环,但是只是一个暂时的、可以被打破的引用循环,不会导致内存泄漏。

时间: 2024-10-09 23:43:14

【转】block强弱引用的相关文章

iOS Block循环引用

前言 本篇文章精讲iOS开发中使用Block时一定要注意内存管理问题,很容易造成循环引用.本篇文章的目标是帮助大家快速掌握使用block的技巧. 我相信大家都觉得使用block给开发带来了多大的便利,但是有很多开发者对block内存管理掌握得不够好,导致经常出现循环引用的问题.对于新手来说,出现循环引用时,是很难去查找的,因此通过Leaks不一定能检测出来,更重要的还是要靠自己的分析来推断出来. 声景一:Controller之间block传值 现在,我们声明两个控制器类,一个叫ViewContr

block循环引用的简单说明

- (void)viewDidLoad {     [super viewDidLoad];     // 如果我们不对block进行copy操作, 那么block存在于栈区, 栈区的block块不会对引用的对象进行持有     // 如果我们对block进行了copy操作, 那么block就存在于堆区, block块就会对引用的对象进行持有          Student *student = [[Student alloc] init];     // 如何解决循环引用问题     //

【少年,放松~】出现block循环引用的三种情况和处理办法

刚入职在看已经上线的项目,其中用到block进行快捷回调的做法很常用,但是Xcode都给给以了如下[循环引用]的警告(如下)的情况,结合网络上的查找和自己的理解,进行总结如下. // Capturing 'self' strongly in this block is likely to lead to a retain cycle 出现这种情况的原因主要是:因为block的特性,声明block的对象都会以copy的形式持有block,而block对于它内部的对象也会进行强引用,从而导致了循环引

iOS 8:【转】Block循环引用

源地址:http://fann.im/blog/2013/04/17/retain-cycle-in-blocks/ 个人笔记,可能会有理解不够透彻而错误. @fannheyward Objective-C 是基于引用计数(retainCount)来做内存管理,ClassA 用到 ClassB 的时候,通过 alloc/retain/copy 等将 objectB.retainCount+1,不需要的时候通过 release/autorelease 将 objectB.retainCount-1

Swift入门教程17-ARC与强弱引用

ARC 全称自动引用计数,是一种内存管理机制.当一块内存的强引用的数目等于0的时候,则这块内存将会被释放. 由于在Swift中,枚举和结构体都是值类型,不通过引用方式进行存储和传递,所以Swift中只有类的实例会进行自动引用计数. 规则:在创建的初始,类的实例的引用计数为1,没增加一次强引用,引用计数加1,每个强引用为nil后,引用计数减1.弱引用不会增加引用计数,关键词weak 注意,不能访问已经被释放了的内存,这样会造成程序崩溃. 一.强弱引用 用下图表示会直观一些 一个强引用,一个弱引用.

iOS Block循环引用精讲

前言 循环引用就是当self 拥有一个block的时候,在block 又调用self的方法.形成你中有我,我中有你,谁都无法将谁释放的困局.又或者解决方法简而言之就一句话的事情:__weak typeof (self) weakSelf = self; 本篇文章精讲iOS开发中使用Block时一定要注意内存管理问题,很容易造成循环引用.本篇文章的目标是帮助大家快速掌握使用block的技巧. 我相信大家都觉得使用block给开发带来了多大的便利,但是有很多开发者对block内存管理掌握得不够好,导

IOS中的block 循环引用和retain cycle (经典)

retain cycle 的产生 说到retain cycle,首先要提一下Objective-C的内存管理机制. 作为C语言的超集,Objective-C延续了C语言中手动管理内存的方式,但是区别于C++的极其非人道的内存管理,Objective-C提出了一些机制来减少内存管理的难度. 比如:内存计数. 在Objective-C中,凡是继承自NSObject的类都提供了两种方法,retain和release.当我们调用一个对象的retain时,这个对象的内存计数加1,反之,当我们调用relea

block 对外部引用变量的处理

一.静态变量 和 全局变量 以及 可变对象(NSMutableArray,NSMutableString)的变量 在加和不加  __block 都会直接引用变量地址.也就意味着 可以修改变量的值.在没有加__block 参数的情况下. 以下所有block 均为 =<__NSStackBlock__: 0x7fff5829e9c0> 栈block ,且 MRC 环境. NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithO

和block循环引用说再见

to be block? or to be delegate? 这是一个钻石恒久远的问题.个人在编码中暂时没有发现两者不能通用的地方,习惯上更偏向于block,没有什么很深刻的原因,只是认为block回调写起来更便捷,直接在上下文中写block回调使得代码结构更清晰,可读性更强.而delegate还需要申明protocol接口,设置代理对象,回调方法与上下文环境不能很好契合,维护起来没有block方便.另外初学者很容易会被忘记设置代理对象坑- 然而惯用block是有代价的,最大的风险就是循环引用