一、内存管理要遵循的原则
1> 谁创建,谁release (看到 alloc、copy、new就应该有写release的冲动)。
2> 谁retain,谁release (简单的来说就是要负责嘛,不能retain后不管了)。
3> 说明下苹果在这方面做的很严谨,后面的学习会接触到ARC,Xcode会帮我们自动管理相应的内存。
二、基本原理
1> 每个对象的内部都封装的一个与之相关的整数,称之为引用计数器。
2> 当使用alloc、new或者copy创建对象时,计数器被设置为1。
3> 给对象发送一条retain消息时候,计数器要+1。(OC当中的消息机制)
4> 给对象发送一条release消息时候,计数器要-1。
5> 当对象的计数器变成0的时候,也就证明这个对象的内存被回收了,这个时候系统就会自动给这个对象发送一个dealloc消息, 一般会重写dealloc方法,在这里释放,一定不要直接调用dealloc方法
6> 可以给对象发送一个retainCount消息,获得当前引用计数器的值。
学生类的声明:
Student.h
1 #import <Foundation/Foundation.h> 2 #import "Book.h" 3 @interface Student 4 @property Book *book; 5 @end
学生类的实现:
Student.m
1 #import "Student.h" 2 @implementation Student 3 @synthesize book = _book; 4 - (void)setBook:(Book *)book{ 5 if (book != _book) { 6 [_book release]; 7 _book = [book retain]; 8 } 9 } 10 - (void)dealloc { 11 [_book release]; 12 [super dealloc]; 13 } 14 @end
说明:自己管理内存泄露多发生在对象的set方法中对象换成员变量的时候(上述代码中出现在学生换书的时候,先判断是不是原来的那本书,然后对原来的书做一次release
,对现有的一本书做一次retain才符合内存管理的原则)。
三、@class 和 #import的区别
1> #import 方式引入,会包含被引用类的所有信息,包括引用类的方法和变量,@class只是告诉编译器有这个类的存在,然而类中的成员变量和方法编译器是不知道的,等在
实现中用到该类的时候在导入对应的头文件。
2> 假如一个类的头文件被许多文件引用,那么这个文件一旦改动了,后面引用这个类的文件都要重新编译,会比较麻烦,效率的话可想而知,但是@class却解决了这个问题。
3> 开发原则是所有类的声明全部放在.h中,类的实现全部放在.m中,如果用到某个类的方法和成员变量在用#import引入头文件。
Student.h改进:
1 #import <Foundation/Foundation.h> 2 @class Book; 3 @interface Student 4 @property (retain) Book *book; 5 @end
Student.m改进:
1 #import "Student.h" 2 #import "Book.h" 3 @implementation Student 4 //@synthesize会自动展开setter和getter, 隐藏了内存管理细节 5 @synthesize book = _book; 6 - (void)dealloc { 7 [_book release]; 8 [super dealloc]; 9 } 10 @end