###检视代码
我们在检查代码时,总是找不到一个好的标准。现在看了这篇文章,我们有共同的标准了!
###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简化了编程,可是再使用的时候,如果不注重细节,仍然有可能会导致内存泄漏,引发程序闪退,所以我们要多注意。
看完这里,觉得有用,可以收藏。