iOS ARC模式下循环引用那点事

博客地址:http://istudying.club/,小编自己搭建的博客哟😀。。。

今天我们来说说循环引用。什么是循环引用?当两个不同的对象各有一个强引用指向对方,导致双方的内存都无法释放的时候,那么循环引用就发生了。

不知道大家有没有听过一句话:人生就像打电话,不是你先挂,就是我先挂。其实用到这里是在合适不过了。假设有两个人打电话,彼此都强引用的对方的电话号码,但是如果双方都不想挂电话的话,那么电话就会一直通着。在OC中也是同样的道理,正常情况下,当一个类或者对象即将释放或者retainCount=0的时候,就会调用dealloc方法,释放相应的内存。但是,当这个对象被其他对象强引用的时候,那么它就不会被回收。此时如果处理不当的话就会造成循环引用。

首先我们先简单的看一个循环引用的例子。首先我们在第二个控制里面,声明一个TestThreeController对象three。

@class TestThreeController;
@interface TestSecController : UIViewController
@property (nonatomic, strong) TestThreeController *three;
@end

然后在.m文件中,定义一个按钮的点击事件用来push,并重写dealloc方法。

- (void)click
{
_three = [[TestThreeController alloc] init];
_three.sec = self;  // 这就是造成循环引用的代码
[self.navigationController pushViewController:_thr animated:YES];
}
- (void)dealloc
{
NSLog(@"TestSecController - dealloc");
}

紧接着我们在第三个控制器里面声明一个TestSecController对象的sec。

@class TestSecController;
@interface TestThreeController : UIViewController
@property (nonatomic, strong) TestSecController *sec;
@end

然后在其.m文件中重写dealloc方法。

- (void)dealloc
{
NSLog(@"ThreeViewController -  dealloc");
}

正常情况下,从TestThreeController控制器pop到TestSecController的时候,会执行ThreeViewController的dealloc方法。但此时可想而知,不会执行,因为循环应用了。其实解决方法很简单,就是将中一个属性修饰符改成weak修饰就好了(关于strong和weak,我这里简单说明一下,一个对象可以有多个指针共同指向,假如A和B两个Strong指针同时指向一个NSString对象”name”,当A重新指向另一个NSString对象”word”时,此时,B仍然指向”name”,如果B也指向别的对象时,因为”name”此时不被任何对象所持有,就会被系统回收。如果B是weak类型的,那么当A重指向的时候,因为B是弱引用,并不持有”name”这个对象,所以”name”就会被系统回收)。

其实OC中代理也是一样的,这里我就拿系统的tableView来举例,我们在控制器中声明一个@property (nonatomic, strong) UITableView *tableView的属性,那么当前控制器就持有了这个tableView,当我们在给tableView设置dataSource和delegate的时候都指向self(也就是当前的控制器),那么tableView也就持有了当前的控制器,所以循环引用便产生了,现在大家应该明白代理为什么用weak或者assign修饰了吧。

现在我们来说一下blcok,相对代理而言,我个人是比较喜欢blcok的。首先解释一下,在声明block时为啥子用copy?因为block原本在栈区,那么它的生命周期由系统管理,如果它所属的变量的作用域结束,那么它就被废弃了。用copy将栈上的block复制到堆上,这样它的生命周期就由我们手动进行管理了,当其超过变量作用域时,堆上的block还可以继续存在。

还有一个问题,是不是OC中所有的blcok都需要我们使用copy手动将其复制到堆上?答案NO,Cocoa框架中使用含有usingBlock方法名的方法,或者GCD的API中传递Block时,我们不需要这么做,也就是说在usingBlock和GCD中的block并不会造成循环引用。所以,如果是我们自己声明的block,在使用的时候,需要注意会不会造成循环引用,而系统提供的block一般不会造成循环引用。

现在我们来说说NSTimer,这里在控制器里面,我们先声明一个属性

@property (nonatomic, strong) NSTimer  *timer;

然后初始化timer

_timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(run) userInfo:nil repeats:YES];

NSTimer为什么会造成循环引用呢,这里我们来分析一下,首先,控制器持有NSTimer,然后在timer初始化的时候,target设置为self,那么timer就持有了当前控制器,这就造成了循环引用,所以在平时我们不使用定时器的时候,记得[_timer invalidate];并且_timer = nil;从而避免循环引用。

说起这个target,我不由得想起了貌似不只有NSTimer有,只有继承UIControl的都有,于是乎,我又在当前控制器声明了一个UIButton,并添加了addTarget,根据上面的逻辑,这不就造成了循环引用了么。说实话,当初我一直也想不通,于是我查阅了一下苹果的官方文档。

对于UIButton,说明如下

The control does not retain the object in the target parameter. It is
your responsibility to maintain a strong reference to the target object
while it is attached to a control

大致意思就是button并不会强引用这个target对象,这样一来,也就不存在循环引用了。

对于NSTimer,说明如下

The object to which to send the message specified by aSelector when the
timer fires. The timer maintains a strong reference to this object until it (the
timer) is invalidated

大致意思就是timer会强引用这个target对象,直到timer执行了invalidate方法。所以,timer在使用的时候需要注意释放的问题,其次NSTimer继承NSObject并不是UIControl,所以不同情况不同对待。

好了,就说这么多了,说的比较简单,如果有什么不对的地方,希望留言指正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容

  • 1.属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作...
    曾令伟阅读 1,062评论 0 10
  • 来自网络 序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了。今年,找过工作人可能会更深刻地体会...
    用心在飞阅读 832评论 5 4
  • 文/Jack_lin(简书作者)原文链接:http://www.jianshu.com/p/5d2163640e2...
    笔笔请求阅读 546评论 0 0
  • 序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了。今年,找过工作人可能会更深刻地体会到今年的就...
    麦兜兜买兜兜阅读 679评论 1 4
  • 目录 属性 修饰词 循环引用 typeof与typedef 1. 属性 objc所有类和对象都是c结构体,cate...
    Ryan___阅读 355评论 0 1