【iOS开发】内存管理之基础介绍,内存管理是程序设计中很重要的一部分,程序在运行的过程中消耗内存,运行结束后释放占用的内存。如果程序运行时一直分配内存而不及时释放无用的内存,会造成这样的后果:程序占用的内存越来越大,直至内存消耗殚尽,程序因无内存可用导致崩溃,这样的情况我们称之为内存泄漏。
在OC中,对象什么时候会被释放(或者对象占用的内存什么时候会被回收利用)?
答案:当对象没有被任何变量引用的时候,就会被释放。
那怎么知道对象已经没有被引用了呢?
OC采用引用计数(reference counting)的技术来进行管理:
1)每个对象都有一个关联的整数,称为引用计数器
2)当代码需要使用该对象时,则将对象的引用计数加1
3)当代码结束使用该对象时,则将对象的引用计数减1
4)当引用计数的值变为0时,表示对象没有被任何代码使用,此时对象将被释放。
与之对应的消息发送方法如下:
1)当对象被创建(通过alloc、new或copy等方法)时,其引用计数初始值为1
2)給对象发送retain消息,其引用计数加1
3)給对象发送release消息,其引用计数减1
4)当对象引用计数归0时,ObjC給对象发送dealloc消息销毁对象
内存管理基本原则,总的来讲有三点:
1)当你通过new、alloc或copy方法创建一个对象时,它的引用计数为1,当不再使用该对象时,应该向对象发送release或者autorelease消息释放对象。
2)当你通过其他方法获得一个对象时,如果对象引用计数为1且被设置为autorelease,则不需要执行任何释放对象的操作;
3)如果你打算取得对象所有权,就需要保留对象并在操作完成之后释放,且必须保证retain和release的次数对等。
for (int i = 0; i < 10000; i ++) { Student * s = [[Student alloc]init]; [s study]; }
该循环内产生大量的临时对象,直至循环结束才释放,可能导致内存泄漏,解决方法和上文中提到的自动释放池常见问题类似:在循环中创建自己的autoReleasePool,及时释放占用内存大的临时变量,减少内存占用峰值。
for (int i = 0; i < 10000; i ++) { @autoreleasepool { Student * s = [[Student alloc]init]; [s study]; } }
然而有时候autoReleasePool也不是万能的。
如果这样做
for (int i = 0; i < 5000; i ++) { CGSize size = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]].size; }
用imageNamed方法加载图片占用Cache的内存,autoReleasePool也不能释放,对此问题需要另外的解决方法。就是采用读文件和autoReleasePool结合的方式。
for (int i = 0; i < 5000; i ++) { @autoreleasepool { CGSize size = [UIImage imageWithContentsOfFile:filePath].size; } }