再来讨论__strong 和 strong
2016-01-16 00:00
239 查看
摘要: ARC __strong和strong
ARC出来挺久了,很多人已经对ARC使用的很熟练,并且研究的很透彻了。不过在这里,我仍然对ARC有些疑问,并提出了一些个人的看法。
ARC不仅多了很多属性关键字,例如weak,strong。也加入了几个所有权修饰符,例如__strong, __weak。很多教程都把这两个直接划等号,例如strong的作用与__strong的作用是一样的,都是把对象的引用计数加1。weak和__weak只是简单的指针指向了这块儿内存,不改变引用计数,起初我也是这么认为,直到我看《iOS和OS X多线程和内存管理》这本书发现了一个问题,才开始重新思考这两者之间的区别。这本书中说道,在ARC环境下,输入以下代码:
你会发现输出结果
如果懂手动管理内存的话,一定会跟我一样感到十分疑惑,这里无论如何都不应该为nil啊,上面的代码,如果用手动管理内存的代码来写,应该是这样的。
MRC下没有显性的调用retain,都是弱引用,不改变引用计数,与上面ARC的代码理论上是一样的,结果估计都很清楚,在这里啰嗦以下,如果只是想让某个文件不使用ARC的话,只需要在"Compile Source"下面找到这个文件,然后加上"-fno-objc-arc"即可。好了,上面的输出结果是这样的:
这个结果并不意外,因为对于alloc出来的对象,引用计数会自动置为1,如果只是简单的指针指向这块儿内存,相当于使用了weak,当然不改变引用计数,而这个过程中,也没有调用releae,autorelease方法,当然也可以使用这个对象。
那__strong和strong是否完全对等?再来看这段代码,我们直接在ARC环境下就能看出问题了。
输出结果:
不知道有没有觉得有些意外。两者的引用计数并不一样,__strong修饰符好像没有起作用,但上面的代码稍微改下,我们再看下输出结果。修改后代码如下,注意比较区别。
输出结果如下:
这个时候一样了。
我们还拿狗和狗链,来比喻对象和引用计数。来给__strong和strong建立模型。来猜测,ARC下苹果到底如何做的处理。有些复杂,如果说的不明白的还望大家可以指出来
__strong:对于一个新创建出来的对象,因为这个时候没有任何指针指向这个新对象,这个时候只要指向这个对象就可以拿到它的所有权,没必要改变引用计数。转为狗和狗链的模型,可以这样认为,一条新领养过来的狗狗默认就带了一条狗链,这个狗链没人牵着,你这个时候只要牵着这条狗,它就归你了。
对于已经有指针,取得了这个对象的所有权,你如果也想拥有,就必须把引用计数+1才可以。狗和狗链的模型就是,看到别人牵着一条狗,你也想拥有这条狗了,那你这个时候,就只能先把狗链从其他狗狗身上解下来,栓到这条狗上面,这样就归你了。而strong这个属性关键字,一直就是这种模型,拿着一条狗链,看到喜欢的狗狗,先把狗链从其他狗狗身上取下来,再栓到自己喜欢的狗上面。
__weak其实感觉跟weak差不多,但是对于一个新对象,ARC下报错的原因可以建立这样的模型。一条新领养的狗狗,你只是看着这条狗狗,但你不想去抓它的狗链,这条狗狗看没人抓狗链,就跑了。你只能远远看着,追也追不上了。以后再也找不到了。所以新的对象会报错的。
上面只是我的一些个人的推测,由于《iOS和OS X多线程和内存管理》对苹果的实现的解读,还有好多没看懂,而且个人感觉有些错误,比如66页最上的代码和70页的代码,对于__strong和__unsafe_unretained的编译器的解读,竟然给出了两份一模一样的代码。实在让我看的有些云里雾里,如果上面的话有错误,还望给我指出来。
ARC出来挺久了,很多人已经对ARC使用的很熟练,并且研究的很透彻了。不过在这里,我仍然对ARC有些疑问,并提出了一些个人的看法。
ARC不仅多了很多属性关键字,例如weak,strong。也加入了几个所有权修饰符,例如__strong, __weak。很多教程都把这两个直接划等号,例如strong的作用与__strong的作用是一样的,都是把对象的引用计数加1。weak和__weak只是简单的指针指向了这块儿内存,不改变引用计数,起初我也是这么认为,直到我看《iOS和OS X多线程和内存管理》这本书发现了一个问题,才开始重新思考这两者之间的区别。这本书中说道,在ARC环境下,输入以下代码:
//ARC环境 __weak UIView *weakView = [[UIView alloc] init]; NSLog(@"weakView = %@", weakView);
你会发现输出结果
weakView = (null)
如果懂手动管理内存的话,一定会跟我一样感到十分疑惑,这里无论如何都不应该为nil啊,上面的代码,如果用手动管理内存的代码来写,应该是这样的。
//非ARC UIView *weakview = [[UIView alloc] init]; NSLog(@"weakView = %@, weakView retainCount = %lu", weakview, weakview.retainCount);
MRC下没有显性的调用retain,都是弱引用,不改变引用计数,与上面ARC的代码理论上是一样的,结果估计都很清楚,在这里啰嗦以下,如果只是想让某个文件不使用ARC的话,只需要在"Compile Source"下面找到这个文件,然后加上"-fno-objc-arc"即可。好了,上面的输出结果是这样的:
weakView = <UIView: 0x7fa142e02dd0; frame = (0 0; 0 0); layer = <CALayer: 0x7fa142e04c10>>, weakView retainCount = 1
这个结果并不意外,因为对于alloc出来的对象,引用计数会自动置为1,如果只是简单的指针指向这块儿内存,相当于使用了weak,当然不改变引用计数,而这个过程中,也没有调用releae,autorelease方法,当然也可以使用这个对象。
那__strong和strong是否完全对等?再来看这段代码,我们直接在ARC环境下就能看出问题了。
//ARC @interface ViewController () { __strong UIView * _testView; } @property (nonatomic, strong) UIView *secondView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _testView= [[UIView alloc] init]; self.secondView = [[UIView alloc] init]; printf("_testView retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(_testView))); printf("secondView retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(self.secondView))); }
输出结果:
_testView retain count = 1 secondView retain count = 2
不知道有没有觉得有些意外。两者的引用计数并不一样,__strong修饰符好像没有起作用,但上面的代码稍微改下,我们再看下输出结果。修改后代码如下,注意比较区别。
//ARC @interface ViewController () { __strong UIView * _testView; } @property (nonatomic, strong) UIView *secondView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIView *view = [[UIView alloc] init]; //先用局部变量指针拿到这个内存地址 _testView = view; //再用 __strong修饰的全局变量指向这个地址。 self.secondView = [[UIView alloc] init]; printf("_testView retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(_testView))); printf("secondView retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(self.secondView))); }
输出结果如下:
_testView retain count = 2 secondView retain count = 2
这个时候一样了。
我们还拿狗和狗链,来比喻对象和引用计数。来给__strong和strong建立模型。来猜测,ARC下苹果到底如何做的处理。有些复杂,如果说的不明白的还望大家可以指出来
__strong:对于一个新创建出来的对象,因为这个时候没有任何指针指向这个新对象,这个时候只要指向这个对象就可以拿到它的所有权,没必要改变引用计数。转为狗和狗链的模型,可以这样认为,一条新领养过来的狗狗默认就带了一条狗链,这个狗链没人牵着,你这个时候只要牵着这条狗,它就归你了。
对于已经有指针,取得了这个对象的所有权,你如果也想拥有,就必须把引用计数+1才可以。狗和狗链的模型就是,看到别人牵着一条狗,你也想拥有这条狗了,那你这个时候,就只能先把狗链从其他狗狗身上解下来,栓到这条狗上面,这样就归你了。而strong这个属性关键字,一直就是这种模型,拿着一条狗链,看到喜欢的狗狗,先把狗链从其他狗狗身上取下来,再栓到自己喜欢的狗上面。
__weak其实感觉跟weak差不多,但是对于一个新对象,ARC下报错的原因可以建立这样的模型。一条新领养的狗狗,你只是看着这条狗狗,但你不想去抓它的狗链,这条狗狗看没人抓狗链,就跑了。你只能远远看着,追也追不上了。以后再也找不到了。所以新的对象会报错的。
上面只是我的一些个人的推测,由于《iOS和OS X多线程和内存管理》对苹果的实现的解读,还有好多没看懂,而且个人感觉有些错误,比如66页最上的代码和70页的代码,对于__strong和__unsafe_unretained的编译器的解读,竟然给出了两份一模一样的代码。实在让我看的有些云里雾里,如果上面的话有错误,还望给我指出来。
相关文章推荐
- JavaScript在网页中画圆的函数arc使用方法
- 25条提高iOS App性能的建议和技巧
- ios高效开发二--ARC跟block那点事
- ios数据存储4种
- iOS中的block和retain cycle (经典)
- ARC 导入 MRC文件
- NSString为啥要使用Copy属性
- iOS编程:学习篇(五)
- IOS在开启ARC的时候忽略某些类中的手写垃圾回收用到的方法
- ARC/非ARC的设置
- Canvas学习笔记二——图形绘制
- 黑马程序员IOS-OC语言-内存管理、ARC
- 认识retain copy assign strong weak 的区别
- Xcode5以后ARC中的闪退问题,内存管理问题
- OC内存管理 MRC与ARC
- 黑马程序员——入学Blog06----内存管理
- 关于ARC的一些说明
- ARC有效的工程中导人非ARC的代码/liberary的设置方法
- iOS arc机制 strong weak
- delegate 作为属性,为什么要用weak修饰?