今天面试问道了循环引用,所以就看了看,原来只是知道使用了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时机。
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方式的,那基本上就没有机会释放这两个对象了。
先简单的介绍这么多,因为这边没有电脑,也不太方便进行例子演示。有电脑了再补上去。这里先做一下记录。
------------------------------------------------------------------------------------结束------------------------------------------------------------------------------------
也很感谢哪位大神能够附上一些例子。