首先这篇文章的只是自已学习中的一些体会,并不可能完正确,如果您觉得我误导了你您 ,请您批评指正,我会在第一时间删除文章,以免误人子弟。
要说这两个字那就不得说内存管理了,那我们就先从MRC 说起吧。首先我建一个很简单的工程项目姑且命名为MemoryTest吧。结构如下,Next Page 跳转到下一页的,返回的时候我监听SecondViewController dealloc 方法执行情况。
再者向项目中添加一个自义类:Test: 什么事情都不做只是重写dealloc 方法:
- (void)dealloc {
[superdealloc];
NSLog(@"Test----dealloc");
}
然后我们在 SecondViewController 声明一个Test属性
@property(nonatomic,retain)Test*test;
重写dealloc 方法:
- (void)dealloc {
[super dealloc];
[_test release];
NSLog(@"SecondViewController----dealloc");
}
然后 我们在viewDidLoad 方法中实例化一个Test对象:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view.
self.test= [[Testalloc]init];
NSLog(@"testRetainCount-------%ld",[self.test retainCount]);
}
那么大家觉得些时的retainCount 是多少? 是1还是2 ? 如果你不确定请自己写个Demo 跑一下看看。 答案是 2 [ _test retainCount] 也是2 。通常我这么做后我们在 dealloc 中 调用 [_test release] 那么引用计数减1 这个时个引用计数不为0 那_test 对象释放吗?因为我重写了Test 的dealloc 方法 如果执行了会输出 "Test----dealloc.这段字符串。然后我跑一下程序看看 有没有输出:
可以看出没有输出,那说明这个对象没有被释放。此时就有内存泄漏了。可以用工具简测下看看。那要怎么解决呢 我们来看段代码dealloc 方法仍然不变, 我们来看下结果:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view.
_test= [[Test alloc] init];
NSLog(@"testRetainCount-------%ld",[self.test retainCount]);
}
跑一下看下输出结果:
可以看出 _test 对象的方法执行了。为什么呢? 请读者思考一下?
然后我们再在 SecondViewController 声明一个属性myArray
@property(nonatomic,retain) NSArray *myArray;
假如我们使用上面方法初始化:
_myArray = [_myArray new]; 这样写没有问题的,我们知道NSArray 有很多类方法可以返回很多自动释放对象如果我们写成这样子:_myArray = [_myArray array]; 可以看出有什么问题吗?为了发现问题我们在重写下viewDidAppear方法:
- (void)viewDidAppear:(BOOL)animated {
[superview DidAppear:animated];
NSLog(@"------%p",_myArray);
}
结果会怎么样呢 跑一下你会发现程序崩掉了,这就其了怪了为什么这样子?,我们再改我初始化改成 self.myArray= [NSArray array]; 我们再跑一下发现没有问题输出了------0x7fdf28f01660。
看到这里我们是不是有疑问呢,或许你已经懂了,用retain关钮字 有时候用self. 会有问题,有时不用的也有会有问题?那什么时候用,什么时候不用呢?我仔细对比两个对象可以得出:
1. 如果返回的对象不是自动释放对象我们不要用self.初始化一个对象。
2.如果返回的象是自动释放对象我们最好用self.初始化一个对象(当然也可以不用,手动的retain 一次也可以解问题)
关于自动对象什么时候释放的问题读者可以自己搜索一下Runloop的知识。看到这里有没有对retain 有一点更深的理解呢,当然我说的只是其中的一小点,有兴趣的朋友可以自己写写看看。
说完了MRC下面,我们再说说ARC 下,选抛出一个问题,reain 关键字等于strong 吗?我们把我项目改成ARC 注意:ARC下是不能主动调用 [super dealloc]; 然后我们再按照上面的方法走一下看看,这里我就不详细一步步说了只说说结果好了。
我们先不改 retain的 关键字的,然后我们初始化self.test= [[Test alloc] init]; 跑下看看这次我们发现输出了,"Test----dealloc" 然后 _test= [[Test alloc] init] 这样子再跑一下:也一样输出 "Test----dealloc" 。我们改成strong 看看我们发现结果完全一样。再换成自动释放对象看看 self.myArray= [NSArray array] 再改成 _myArray= [NSArray array]; 我们发现这两次都没有问题都正确输出_myArray的地址。这样子看来 retain 在ARC却实等价的。
但是从MRC 和ARC下的分析来看他们内部结构应该不同的,MRC下会引发的问题ARC 下都没有发现,说明ARC 下应该是对strong 和retain 进行了优化。本质他们应该不是等价的。也有可能ARC retain 被直接替换成了strong 至他们内部应该是怎么样实现的,我也没有办法解释,还望有理解的大牛能指点一二。看到这里我们是不是应该理解下其他关键字呢
在这里也扯点闲话我们现在很多项目使用ARC 很多人用Java一样不再关心内存问题了,也不深入去学习object-c的基础知识了。最近面试了很久了@property后面可以有哪些修饰符?没有一个能回答完整的。很多人也越来越浮躁了,别人工资多少我就是多少?而不是我说的技术值多少。在这里我想对那些刚刚接触iOS开发的人说,一定要学好objetive-c 基础知识,静下来好好的学习一下MRC不是说MRC过时了就没有学习了必要,踏踏是学学才能对内存管理有清析的认识。我们时刻把内存的问题放在心上,要用最小内存去完成我们想要完成事。而不是只求功能实现就成万事大吉了。
有时间的话下次就分析一下,NSSting 为什么用Copy 好?也顺便分析下copy 也告诉您些你老师没有说有东西。