原文地址:http://www.joky.me/learn_ios_1/
创建一个对象系统做了哪些事
- 分配内存空间,存储对象
- 初始化成员变量
- 返回对象的指针地址
对象在完成创建的同时,内部会自动创建一个引用计数器(retainCount)。这个计数器是系统用来判断是否回收对象的唯一依据,当我们的引用计数retainCount = 0的时候,系统会毫不犹豫回收当前对象
[对象 release] retainCount - 1
[对象 retain] retainCount + 1
当引用计数retainCount = 0时,对象就被销毁了。当一个对象要被销毁的时候,系统会自动调用该对象的dealloc函数,通知对象 你将要被销毁
内存管理原则(配对原则):只要出现了 new, alloc, retain 就一定配对出现一个release或者autorelease
注意:重写dealloc函数时一定要调用[super dealloc]
手动内存管理需要注意哪些问题
- 野指针操作
- 对象已将被回收,如果再调用该对象的方法或属性就会触发野指针操作。被系统回收的对象被称为僵尸对象,默认情况下XCode为了提高编码效率,不会实时检查僵尸对象
- 当一个对象的retainCount已经为0时,调用retain方法是不会使对象起死回生的,同时还会触发野指针异常 (EXC_BAD_ACCESS)
如果确定当前作用域中的对象已将不会再被使用了,为了防止野指针操作,通常我们会把不再使用的指针变量赋值为nil
- 内存泄露
- 只要对象的retainCount 不为0,该对象就会一直存在内存中。内存泄露是指,不再被使用的对象一直在内存中没有被销毁
- 如果在对象的retainCount不为0时,将指向对象的指针赋值为nil,可能会导致内存泄漏
多个对象的内存管理
- 手动内存管理中对象类型的set方法内部实现
- (TypeName *) setObject: (TypeName *) object
{
//判断两个对象的内存地址是否相同
if(_object != object)
{
//release 旧值
[_object release];
//retain 新值
_object = [object retain];
}
}
//一定要在dealloc中调用对象的 release 方法
- (void) dealloc
{
[_object release];
[super dealloc];
}
@property
@property做了哪些事情
- 生成 get 与 set 方法的声明
- 生成 get 与 set 方法的简单实现
- 如果没有声明相应对象的成员变量,那么它会自动生成一个以下划线(_)开头的成员变量
@property 的参数分为4类
- 与set方法内存管理相关的参数
- retain: 要生成符合内存管理原则的set方法(应用于对象类型)
- assign: 直接复制(对象类型,基本数据类型)
- copy: 复制对象
- 多线程相关
- nonatomic: 不生成多线程相关代码 (效率较高)
- atomic: 生成多线程相关代码 (如果不写,默认是这种方式)
- 是否要生成set与get方法
- readwrite: 读写属性,同时生成set与get方法
- readonly:只读属性,只生成get方法
- set与get方法名称相关的参数
- setter: 设置生成的set方法名称
- getter: 设置生成的get方法名称, 一般用在BOOL类型
//getter的使用
@property (nonatomic,assign,getter = isVip, setter=vip) BOOL vip;
如果一个对象被声明成了成员变量或者使用@property生成了符合内存管理的set方法,那么一定要在dealloc函数调用该对象的release方法
手动内存管理 类相互引用的问题
如果程序中出现两个类相互引用的问题,那么其中一个类要改成assign方式,不能使用retain(会导致内存泄露问题)。并且需要将 @import 类.h 改成 @class 类名;