局部变量放在栈里边 指针*p
动态变量在堆里,如Person对象
堆要手动释放
需要清空: p = nil;
僵尸对象:所占用内存已经被回收的对象。僵尸对象不能再使用。
野指针:指向僵尸对象(不可用内存)的指针
空指针:没有指向任何东西的指针(存储的东西是nil、NULL、0),给空指针发送消息不会报错
OC中不存在 空指针错误
/* 1.方法的基本使用 1> retain :计数器+1,会返回对象本身 2> release :计数器-1,没有返回值 3> retainCount :获取当前的计数器 4> dealloc * 当一个对象要被回收的时候,就会调用 * 一定要调用[super dealloc],这句调用要放在最后面 2.概念 1> 僵尸对象 :所占用内存已经被回收的对象,僵尸对象不能再使用 2> 野指针 :指向僵尸对象(不可用内存)的指针,给野指针发送消息会报错(EXC_BAD_ACCESS) 3> 空指针 :没有指向任何东西的指针(存储的东西是nil、NULL、0),给空指针发送消息不会报错 */ #import <Foundation/Foundation.h> #import "Person.h" int main() { // 1 Person *p = [[Person alloc] init]; //NSUInteger c = [p retainCount]; //NSLog(@"计数器:%ld", c); // 2 retain方法返回的是对象本身 [p retain]; // 1 [p release]; // 0 野指针:指向僵尸对象(不可用内存)的指针 [p release]; [p retain]; // -[Person setAge:]: message sent to deallocated instance 0x100109a10 // 给已经释放的对象发送了一条-setAge:消息: p.age = 10; //[p setAge:10]; // 指针p变成空指针 //p = nil; // EXC_BAD_ACCESS : 访问了一块坏的内存(已经被回收、已经不可用的内存 // 野指针错误 // OC不存在空指针错误,给空指针发送消息,不报错 [p release]; [p release]; [p release]; [p release]; [nil release]; return 0; }
要想手动调用retain、release等方法,在创建项目的时候不要勾选ARC
默认情况下,Xcode是不会管僵尸对象的,使用一块被释放的内存也不会报错。为了方便调试,应该开启僵尸对象监控
====防止给空指针发送消息不报错
如果你有个OC对象类型的成员变量,就必须管理这个成员变量的内存。比如有个Book *_book
- (void)setBook:(Book *)book {
if (book != _book) {
[_book release];
_book = [book retain];
}
}
- (void)dealloc {
[_book release];
[super dealloc];
}
内存管理代码规范:
1.只要调用了alloc,必须有release(autorelease)
对象不是通过alloc产生的,就不需要release
2.set方法的代码规范
1> 基本数据类型:直接复制
- (void)setAge:(int)age
{
_age = age;
}
2> OC对象类型
- (void)setCar:(Car *)car
{
// 1.先判断是不是新传进来对象
if ( car != _car )
{
// 2.对旧对象做一次release
[_car release];
// 3.对新对象做一次retain
_car = [car retain];
}
}
3.dealloc方法的代码规范
1> 一定要[super dealloc],而且放到最后面
2> 对self(当前)所拥有的其他对象做一次release
- (void)dealloc
{
[_car release];
[super dealloc];
}
OC对象类型
@property (nonatomic, retain) 类名 *属性名;
@property (nonatomic, retain) Car *car;
@property (nonatomic, retain) id car;
//被retain过的属性,必须在dealloc方法中release属性
- (void) dealloc {
[ _car release];
[ super dealloc]
}
非OC对象类型
@property (nonatomic, assign) 类型名称 属性名;
@property (nonatomic, assign) int age;
对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类
这种代码编译会报错。当使用@class在两个类相互声明,就不会出现编译报错
使用 @class 类名; 就可以引用一个类,说明一下它是一个类,告诉编译器Person是一个类
l #import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息
l 如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来 讲,使用@class方式就不会出现这种问题了
l 在.m实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用#import方式引入被引用类
@autoreleasepool
{
// ....
}
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// .....
[pool release]; // 或[pool drain];
好处:不用关心对象释放的时间 2,不用关心什么时候调用release
使用注意:占用内存较大的对象不要随便使用
l 以前:
Book *book = [[Book alloc] init];
[book release];
l 现在:
Book *book = [[[Book alloc] init] autorelease];
// 不要再调用[book release];
+ (id)book {
return [[[Book alloc] init] autorelease];
}
外界调用[Book book]时,根本不用考虑在什么时候释放返回的Book对象
NSNumber *n = [NSNumber numberWithInt:100];
NSString *s = [NSString stringWithFormat:@"jack"];
NSString *s2 = @"rose";
原文:http://www.cnblogs.com/IDRI/p/4983084.html