您的位置:首页 > 其它

再来讨论__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环境下,输入以下代码:

//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的编译器的解读,竟然给出了两份一模一样的代码。实在让我看的有些云里雾里,如果上面的话有错误,还望给我指出来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ARC strong __strong weak __weak