关于 ARC,有疑问请教

2015-02-06 17:42:43 +08:00
 georgetso
问题1
- (void)aMethodInAClass:(NSData *)data {
NSString *s = [[NSString alloc] initWithData:data encoding:4];
......
s = nil;
}

请问以上方法中, s = nil 是否是必须的?

问题2
@interface Person {
NSString * __strong name;
}
@property NSString *name;
@end
在这样的类定义中,是否需要在 dealloc 方法中 nil out name?
如果需要,那么 self.name = nil 和 name = nil 的区别是?
2102 次点击
所在节点    iDev
7 条回复
66450146
2015-02-06 18:03:30 +08:00
1. 不需要
2. 不需要

ARC 就是这么任性
Madimo
2015-02-06 18:05:05 +08:00
1.不是
2.不需要
在开启 ARC 的情况下,只要避免循环引用,所有的变量都会被正确释放。
noli
2015-02-06 18:20:03 +08:00
要理解ARC,了解一个变量的作用域是很有必要的。

1. 变量 s 的作用域位是 aMethodInAClass 方法“被调用”的期间,执行完方法后方法就退栈了,所以s也会被回收,这种情况是ARC可以在编译期就知道的,所以可以正确插入回收代码。

2. 成员 name 的作用域是 与具体的 Person 对象绑定的。

就是说,只要 Person对象存在,name 就存在,只要Person 对象退出作用域或者说生命周期结束(就是 dealloc 之后),name 也会结束。

没有形成循环引用的前提下,因为 objc 对对象的引用都可以追朔到栈上,所以Person 的生命周期可能的结束点可以肯定,必然不晚于某个函数return 时,也就是跟 s 的情形一样,是可以由编译器操纵引用计数的。所以,对于这种不可能形成循环引用的对象,在 dealloc 里面写不写 nil out 是没有区别的。

但假如 Person 里面有一个 MyFacebook,MyFacebook 里面会引用Person 对象,那么这个时候就有可能形成循环引用。就应该根据条件 在 dealloc 之前(而不是在 dealloc 里面) nil out MyFacebook 类型的变量,避免循环引用。
tane05
2015-02-06 18:59:06 +08:00
1, 2楼言简意赅 ps问题2还有个知识点实例变量和属性的区别
huoshanhui
2015-02-06 19:19:52 +08:00
@tane05 实例变量就是实例变量。属性会 synthesize 一个 _variable。
kobe1941
2015-02-08 18:05:29 +08:00
1.不是。因为ARC的本质是编译器帮你管理内存,编译器在编译的时候会自动在合适的地方插入retain release 或者autorelease,所以大多数东西的内存开发者不需要理会,但是定时器NSTimer和通知还有CF开头的一些东西需要自己管理。
2.不需要。你这么写,该类会有两个成员变量,name与_name,用self.name调用的是_name。建议所有成员变量,如果可以,尽量都写成属性。

另外,字符串类的属性,一般用nonatomic和copy属性修饰,养成好习惯。
canautumn
2015-02-12 12:48:44 +08:00
我也来补充一个,在block里引用实例变量有隐性的self retain,容易造成隐藏的循环引用,所以要用一个指向自身的弱引用在block里引用实例变量,但是如果是concurrency的话坑就来了,这个弱引用可能在block执行一半的时候突然变成了nil,就crash了。这就需要在block里边复制一份强引用。不过属性没有后者的问题,因为给nil发消息不会crash……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/168857

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX