iOS开发之OC语法基础(四)--内存管理

来源:互联网 发布:ajax获取前台数据 编辑:程序博客网 时间:2024/05/24 01:04

一、课程目标:

1、掌握内存管理的原则

2、深入理解属性的内存管理

3、掌握便利构造器内存管理

4、掌握NSAutoreleasePool(自动释放池)的使用

二、如何管理内存?

1、解决办法:

有创建,就要有销毁

所谓 内存管理:针对创建和销毁过程进行管理

2、管理方式:

垃圾回收(java、C#等)

人工管理(OC、C、C++)

自动管理内存(ARC、IOS5新特性),并非垃圾回收

3、引用计数:

OC采用“引用计数机制”(retainCount)管理对象所占用的内存

计数:计数器,用于统计数字。例如:1、2、3...等

引用计数:某一块内存,拥有这块内存的拥有着的个数。

注意:在OC语言中,NSObject类以及子类的实例对象包含一个整型属性,用来统计当前的引用计数

4、生命周期

实例对象的生命周期

出生于alloc方法

死亡于dealloc方法

注意:通过对类发送alloc消息,获得的实例对象的引用计数赋值为1!

注意:当实例对象的引用计数为0时,自动对该实例对象发送dealloc消息!

5、常见方法

copy制造一个副本,将副本的引用计数赋值为1,拥有副本的所有权。

retain对象引用计数+1,并拥有对象所有权。

release对象引用计数-1,并放弃对象所有权。

autorelease未来某个时间对象引用计数-1,并放弃对象所有权。


引用计数的变化

Student * stu = [[Student]init];NSLog(@“创建时计数为:%lu”,[stu retainCount]);[stu retain];//调用了retain方法,计数器应该加1NSLog(@“retain后计数为:%lu”,[stu retainCount]);[stu release];//计数器减一[stu release];//计数器再减一

6、指针变量与对象

对象是放在堆里的

指针变量时放在栈里的

唯一的联系:指针变量存的是对象的地址

7、对象的实例属性

@property Student * stu;

//设置器- (void)setStu:(Student *)stu{<span style="white-space:pre"></span>_stu = stu;}//访问器- (Student)stu{<span style="white-space:pre"></span>return _stu;}

代码执行步骤:


然后执行:[student release];


然后执行:[mc.stu sayHi];


注意:地址为0x10ff78c的student对象已经被销毁,无法接收sayHi消息,程序崩溃!

为了解决崩溃:

@property(retain,nonatomic) Student * stu;
//设置器- (void)setStu:(Student *)stu{<span style="white-space:pre"></span>[stu retain];<span style="white-space:pre"></span>[_stu release];_stu = stu;}//访问器- (Student)stu{return _stu;}
代码执行步骤:

注意:地址为0x10ff78c的student对象没有被销毁,可以接收sayHi消息,程序正常!


dealloc方法在对象引用计数为0的时候自动调用

主要用于释放自身所占有的资源,永远不要手动调用dealloc


8、便利构造器内存管理

阅读下面代码,看内存是否有问题

+ (id)studentWithName:(NSString *)name                  andAge:(NSInteger)age               andHobby:(NSString *)hobby               andAddress:(<span style="font-family: Arial, Helvetica, sans-serif;">NSString  *</span>)address{    Student *student = [[Student alloc]initWithName:name            andAge:age andHobby:hobby andAddress:address];    [student release];    return student;}
注意:地址为0x10ff78c的student对象已经被销毁,虽然将地址返回,但已经不能接受消息!!!

那么便利构造器要怎么进行内存管理呢,我们需要用到自动释放池


自动释放池:

NSAutoreleasePool类

当创建的对象未来某个时候销毁时,可以使用对象的autorelease方法

对象将所有权交给最近的NSAutoreleasePool对象

当池对象drain或release时,会逐一对池内对象发送release消息

尽量不要使用autorelease,而是使用release

便利构造器

+ (id)studentWithName:(NSString *)name                  andAge:(NSInteger)age               andHobby:(NSString *)hobby               andAddress:(NSString  *)address{    Student *student = [[Student alloc]initWithName:name            andAge:age andHobby:hobby andAddress:address];    return [student autorelease];//不立即释放,而是交给autoreleasepool}
自动释放池
//较早版本的创建NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];<pre name="code" class="objc">Student * stu = [[Student alloc]init];//alloc一个对象[stu autorelease];// 将所有权控制交给pool,stu不用手动release了...
[pool release];
//现版本的创建@autoreleasepool{    Student * stu = [[Student alloc]init];//alloc一个对象    [stu autorelease];// 将所有权控制交给pool,stu不用手动release了    ...}

示例1:

+ (id)personWithName:(NSString *)aName{Person * person = [[Person alloc]initWithName:aName];return [person autorelease];}
示例:
- (void)printName{NSString *name = @"hello";NSLog(@"%@",name);}

- (void)printHello{NSString *str = [NSString stringWithFormat:@"Hello"];NSLog(@"%@",str);}
9、内存检测工具

Analyze内存静态分析(编译期)

leaks内存泄露检测工具(运行期)


三、总结

内存管理原理:

凡是alloc、retain、copy的地方,都应出现release或autorelease与之对应

属性为retain或copy的话,需要在类的dealloc中释放这个属性

便利构造器本身应包含autorelease

一定不要释放没有所有权的对象。不要手动调用dealloc

四、术语与技巧

ios程序开发离不开内存管理。虽然原则很简单,但是真正做好内存管理还是比较困难的。

法宝:只要自己使用了alloc、retain、copy,就一定要有对应的release、autorelease,它们要配对使用。

工具:Analyze和Instruments(leaks)

必杀技:dealloc中打印NSLog,看dealloc是否执行



0 0