今天面试问道了循环引用,所以就看了看,原来只是知道使用了Block容易造成循环引用。今天就来简单的介绍一些循环引用。

先来简单介绍一下什么是循环引用?

循环引用可以简单的理解成:A对象引用了B对象,B对象又引用了A对象。两者相互保持对方的一个引用。导致任何时候计数都不为0,最终两者都无法释放。

产生循环引用的方式:

1、NSTimer

比如说我在一个类中声明了一个NSTimer计时器类。而在NSTimer 的方法

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
target:(id)target
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)repeats

当我们在aSelector中调用了自己的属性或者方法时(比如调用了自己的self.class),那么当我们实例化这个类之后然后我们让他延迟几秒释放,那么我们会发现time中的aSelector会一直执行。现在就来简单的分析一下吧:

timer没有调用invalidate方法是不会因为类的释放而停止的。而对于类实例来说:它认为timer没有执行完毕,所以没有机会进入dealloc。循环引用,相互等待。所以我们可以在类实例释放之前手动调用一下NSTimer的invalidate方法。还有就是下面的代码:

__weak ClassA *weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:weakSelf selector:@selector(startTimer) userInfo:nil repeats:YES];

所以我们在使用NSTimer时一定要注意NSTimer的invalidate时机。

在下面更新中,对NSTimer进行了重新说明。NSTimer是会造成循环引用,但是只要我们在合适的地方将其停止并释放就没问题。但是你有的时候并不能保证其一定会释放,比如我点击了倒计时,但是我没有等倒计时结束就返回,如果是ViewController,你可以在视图将要消失的时候调用停止和释放方法。但是如果不是在ViewController中就不确定了。所以在gitHub上的demo上有个ZGWeakTimerTarget,可以巧妙地解决循环引用问题。更多请参见这里.

2、Block

例如我们定义了一个block块,然后作为了一个类的属性变量,那么当我们在这个块中调用自己的属性或者方法的时候就会产生循环引用。

解决循环引用方法:通过__weak声明一个self的新变量来代替原来的self。这样在块中可以通过这个弱引用self来防止block中对self进行strong引用。

3、delegate

一般情况下我们声明delegate时使用assign赋值,因为赋值属性不会增加计数。

如果一个UITableViewController 对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a, 如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。

---------------------------------------------------------------------------------------------------------

2016年6月7日更新:

引用循环定义:
所谓的“引用循环”是指双向的强引用,所以那些“单项的强引用”(block强引用self)是没有问题的。 
 
2017年6月19日更新:
近期分享的PPT和DEMO。详见这里

iOS循环引用问题的更多相关文章

  1. iOS循环引用

    iOS循环引用 当前类的闭包/Block属性,用到了当前类,就会造成循环引用 此闭包/Block应该是当前类的属性,我们经常对Block进行copy,copy到堆中,以便后用. 单方向引用是不会产生循 ...

  2. iOS 循环引用解决方案

    一.BLOCK 循环引用 一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身.构成循环引用. // 定义 block 的时候,会对外部变量做一次 cop ...

  3. iOS 循环引用

    1.循环引用一般是指:A持有B,B同时持有A,从而导致死循环无法释放对象. 2.一般循环引用出现在block和delegate中,而一般解决方法就是将self变成weakSelf(强引用变成弱引用), ...

  4. iOS 循环引用讲解(中)

    谈到循环引用,可能是delegate为啥非得用weak修饰,可能是block为啥要被特殊对待,你也可能仅仅想到了一个weakSelf,因为它能解决99%的关于循环引用的事情.下面我以个人的理解谈谈循环 ...

  5. iOS循环引用常见场景和解决办法

    好多场景会导致循环引用,例如使用Block.线程.委托.通知.观察者都可能会导致循环引用. 1.委托 遵守一个规则,委托方持有代理方的强引用,代理方持有委托方的弱引用. 实际场景中,委托方会是一个控制 ...

  6. iOS 循环引用 委托 (实例说明)

    如何避免循环引用造成的内存泄漏呢: 以delegate模式为例(viewcontroller和view之间就是代理模式,viewcontroller有view的使用权,viewcontroller同时 ...

  7. iOS之weak和strong、懒加载及循环引用

    一.weak和strong 1.理解 刚开始学UI的时候,对于weak和strong的描述看得最多的就是“由ARC引入,weak相当于OC中的assign,但是weak用于修饰对象,但是他们都不会造成 ...

  8. 【转】iOS学习之容易造成循环引用的三种场景

    ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...

  9. 【原】iOS容易造成循环引用的三种场景,就在你我身边!

    ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...

随机推荐

  1. MVVMlight框架应用:Data Binding、Command

    常用Wpf开发中我们在ViewModel中实现INotifyPropertyChanged接口,通过触发PropertyChanged事件达到通知UI更改的目的:在MVVMLight框架里,这里我们定 ...

  2. vs2010设置

    解决方案管理器文件自动定位:工具--选项--项目和解决方案--常规--在解决方案资源管理器中跟踪活动项(前打勾). VAssistX拼写错误的下划波浪线去掉:在VAssistX菜单栏->Visu ...

  3. Mina、Netty、Twisted一起学(一):实现简单的TCP服务器

    MINA.Netty.Twisted为什么放在一起学习?首先,不妨先分别看一下它们官方网站对其的介绍: MINA: Apache MINA is a network application frame ...

  4. 编写高质量JS代码的68个有效方法(六)

    [20141213]编写高质量JS代码的68个有效方法(六) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  5. cereal:C++实现的开源序列化库

    闲来无事发现了一个基于C++实现的序列化工具,相比于其他(比如Boost serialization或Google protobuf,恰巧都用过,以后再介绍),使用简单,感觉不错,下面做个摸索. ce ...

  6. 使用Architecture Explorer分析应用程序及使用层次图

    使用Architecture Explorer分析应用程序 Architecture Explorer和依赖图可以帮助我们了解所有的项目,包括小项目和大项目.Architecture Explorer ...

  7. sprint个人总结+读书博客

    读书感想:    第8章讲了需求分析,在我的日常软件编写中,肯定需要需求分析的,一个没有需求的软件,编写出来也没有什么意义,只能是丢在一个角落里发霉.需求有各种各样,要怎样才能满足客户的需求呢,那就要 ...

  8. Sprint回顾-0525

    1.回顾组织 主题:“我们下次怎么样才能更加认真对待?” 时间:设定为1小时. 参与者:整个团队. 场所:宿舍走廊. 秘书:团队队长秘书,筹备.记录.整理.   2.回顾流程    Sprint总结: ...

  9. MVC知识点01

    1:母版页都 放在View/Shared里面,而且全部的视图页面都可以去用母板页. **母板的应用要用到嵌套,@RenderBody();将别的网页的内容全部显示在此处,它就相当于一个占位符. 2:架 ...

  10. Windows 8.1 去掉库的方法

    Windows 8.1[这台电脑],  里面又多了[文件夹]分类,真是各种不习惯 删除方法: 打开注册表, 找到 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wind ...