【ARC&MRC】深入理解

###检视代码

我们在检查代码时,总是找不到一个好的标准。现在看了这篇文章,我们有共同的标准了!

###ARC 和 MRC深入理解

###由来

在iOS1.0的时候,苹果公司没有开放手机开发接口,不存在iOS开发者这个概念。
在iOS2.0的时候,我们管理内存使用的技术数MRC机制。
在iOS5.0的时候,苹果公司推出了ARC机制。

###使用

MRC管理内存的时候,我们需要遵守“谁创建,谁释放,谁引用,谁管理”。
ARC的时候,很多人都说iOS的ARC和Android的GC机制很像,但是他们本身还是有很大的区别的。其中GCS是运行时特性,ARC是编译时特性。

ARC是编译时特性,并不是运行时特性。

###ARC细则

强引用指向的对象不会被释放。
一个对象没有强引用会立刻释放。
弱引用指向的对象将要释放时自动为空。
注意:我们创建的对象默认是强引用,比如:People = [People new];等价__strong People = [People new];

##深入理解 变量持有情况

###例子一 局部对象

@implementation People  
-(id)init  
{  
    if (self = [super init])  
    {  
        NSLog(@"%s",__FUNCTION__);  
    }  
    return self;  
}  
-(void)dealloc  
{  
    NSLog(@"%s",__FUNCTION__);  
}  
@end  

//People.m 

我们在viewDidLoad中添加People *p = [People new]; NSLog(@"%s",__FUNCTION__);

打印结果

2015-10-19 13:16:10.589 goswift[2627:83432] -[People init]
2015-10-19 13:16:10.600 goswift[2627:83432] -[ViewController viewDidLoad]
2015-10-19 13:16:10.600 goswift[2627:83432] -[People dealloc]

一句话总结: 一个对象没有强引用会立刻释放

###微变化

我们在viewdidload中添加下面代码,打印该如何?
__weak People *p = [People new];
NSLog(@"%s",__FUNCTION__);

验证打印结果

2015-10-19 13:22:10.783 goswift[2682:96983] -[People init]
2015-10-19 13:22:10.783 goswift[2682:96983] -[People dealloc]
2015-10-19 13:22:10.784 goswift[2682:96983] -[ViewController viewDidLoad]

因为对象没有强指针引用,所以People会被释放,然后执行上面的打印。

###例子二 全局变量

现在将People定位全局变量

我们在viewDidLoad中写下面代码:
_people = [People new];
NSLog(@"%s",__FUNCTION__);

打印结果:

2015-10-19 13:28:32.076 goswift[2764:100790] -[People init]
2015-10-19 13:28:32.077 goswift[2764:100790] -[ViewController viewDidLoad]

因为执行完了,People是一个强引用,所以不会释放People ###微改变

如果在 __weak People * people;

再看打印结果

2015-10-19 13:31:47.816 goswift[2803:102843] -[People init]
2015-10-19 13:31:47.827 goswift[2803:102843] -[People dealloc]
2015-10-19 13:31:47.828 goswift[2803:102843] -[ViewController viewDidLoad]

虽然是全局对象,但是弱引用,没有强引用,所以会释放。

###例子三 全局和局部混合使用

定义一个全局行强指针People的对象p,同时创建一个局部性强指针对象p1.

viewdidload中
People * p1 = [People new];
p = p1;

打印结果:

2015-10-19 13:49:32.380 goswift[3088:111876] -[People init]
2015-10-19 13:49:32.383 goswift[3088:111876] -[ViewController viewDidLoad]

理论上讲应该释放p1,但是没有,是因为p1赋给了p 被全局持有,所以没释放

##例子四 创建对象嵌套

假设我们还有一个类,类名为Car,People有一个属性,@property(nonatomic,strong) Car *car;
现在我们把People声明一个全局对象p。
p = [People new];
Car *ca = [Car new];
p.car = ca;
NSLog(@"%s",__FUNCTION__); 

打印结果:

2015-10-19 13:57:21.883 goswift[3220:116572] -[People init]
2015-10-19 13:57:21.886 goswift[3220:116572] -[Car init]
2015-10-19 13:57:21.886 goswift[3220:116572] -[ViewController viewDidLoad]

没有释放,Car虽然是局部引用,但是函数执行完毕后没有释放,因为p对其还有一个强引用,所有Car不会被释放掉。 如果我们将People释放掉,Car自然也会释放。 我们想要释放一个一个变量的话,我们可以直接将变量赋值为空,就会释放掉。

###扩展例子 循环引用

如果Car的对象中包含People, People中也包含Car, 就构成了交叉引用

Viewdidload中写:
People * p = [People new];  
Car *c = [Car new];  
p.car = c;  
c.people = p;  
NSLog(@"%s",__FUNCTION__);

打印结果:

2015-10-19 14:05:50.296 goswift[3320:121202] -[People init]
2015-10-19 14:05:50.298 goswift[3320:121202] -[Car init]
2015-10-19 14:05:50.298 goswift[3320:121202] -[ViewController viewDidLoad]

在属性修饰的时候,不要同时使用strong,可以一个使用weak修饰,则运行结果如下

###总结

虽然arc简化了编程,可是再使用的时候,如果不注重细节,仍然有可能会导致内存泄漏,引发程序闪退,所以我们要多注意。
看完这里,觉得有用,可以收藏。

转载于:https://my.oschina.net/kshopping/blog/683820

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值