OC-内存管理

来源:互联网 发布:主机电源检测软件 编辑:程序博客网 时间:2024/05/12 10:05

OC-内存管理

 

App会开辟内存空间的操作:

创建OC对象、定义变量、调用一个函数或方法


内存管理:分配内存、释放内存

 

内存管理范围:任何继承了NSObject的对象,对其他非对象类型无效(int, char, float, double, struct, enum 等)

原因:OC对象存放于内存中的堆中,非OC对象存放于栈里,系统会自动回收栈空间


系统回收内存原理:

判断对象的引用计数器,如果引用计数器等于0就自动回收

所以要管理内存,就要学习操作引用计数器:

retain:引用计数器加1

release:引用计数器减1

retainCount:当前的值

 

当retainCount = 0时,系统自动调用dealloc方法,一般可以通过重写deallco方法查看是否有内存泄露

重写dealloc方法:

-(void)dealloc

{

                       NSLog(@”dealloc方法被调用”);

                       [superdealloc];

}

 

僵尸对象:已经被销毁的对象

 

野指针:指向僵尸对象的指针(经典报错:EXC_BAD_ACCESS, 给野指针发了消息)

 

空指针:没有指向任何空间的指针(nil, 即是0, 给空指针发消息不会报错)

 

为了避免野指针错误常见方法:

当对象销毁后,将该野指针变成空指针

 

多对象的内存管理

管理规律:

1.只要还有人使用,该对象就不会被回收。

2.想使用某个对象,就让对象的计数器加1。

3.不在使用这个对象,就将该对象的计数器减1。

 

苹果官方内存管理原则:

1.   谁创建谁release:如果通过alloc、new、或copy创建一个对象,那就必须调用release或autorelease

2.   谁retain谁release

 

Person对象拥有一只狗对象

Person类的set方法:

- (void)setDog:(Dog *)dog

{

    //如果新对象与旧对象不同,即换了一个同样的对象

    if(_dog != dog) {

       //对当前的对象(旧对象)release

       [_dog release];

       //对新对象retain

       _dog = [dog retain];

    }

}

 

Person类的dealloc方法:

- (void)dealloc

{

    //当人消失了,代表那个人的狗也没了,必须对旧对象release

    [_dogrelease];

    [superdealloc];

}

 

以下错误写法会引发内存泄露

    //错误写法1

   [[Dog alloc] init].weight = 10.8;

    //错误写法2

    Person*p = [[[Person alloc] init] autorelease];

   p.dog = [[Dog alloc] init];

 

 

@property参数

 

控制set方法的内存管理

-retain:release旧值,retain新值,(用于OC对象)

-assign:直接赋值,不做任何内存管理(默认,用于非OC对象)

-copy:release旧值,copy新值(一般用于NSString *)

 

控制需不需生成set方法

readwrite:同时生成set、get方法(默认)

readonly:只生成get方法

 

多线程管理

atomi:性能低(默认)

nonatomic:性能高

 

控制set方法和get方法的名称

setter:设置set方法的名称,带:

getter:设置get方法的名称

 

@class

作用:可以简单的引用一个类

@class Car;

告诉编译器Car是一个类,不会包含Car的属性和方法

 

具体使用:

在.h文件中使用@class引用一个类

在.m文件中使用#import包含这个类的.h文件

 

@class和#import区别

#import会包含引用类的所有信息(内容), 包括引用类的变量和方法

@class仅仅是告诉编译器有这么一个类, 具体这个类里有什么信息, 完全不知

 

效率上的区别

如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍 , 编译效率非常低

相对来讲,使用@class方式就不会出现这种问题了

 

@class可以循环引用,#import不能循环引用

 

 

循环retain:如人拥有一只狗,狗有一个主人

弊端:导致人、狗对象都无法释放

解决:当两端互相引用时,应该一端用assign,一端用retain

 

autorelease

作用:将自动释放池里的对象做一个release操作

 

使用release

Book *book = [[Book alloc] init];

[book release];

 

使用autorelease

Book *book = [[[Book alloc] init] autorelease];

// 不要再调用[book release];

 

使用场合

一般可以为类添加一个快速创建对象的类方法

+ (instancetype)book {

    return[[[self alloc] init] autorelease];

}

外界调用[Book book]就可以获得和使用新建的Book对象,根本不用考虑在什么时候释放Book对象

 

一般来说,除了alloc、new或copy之外的方法创建的对象都被声明了autorelease

比如下面的对象都已经是autorelease的,不需要再release

NSNumber *n = [NSNumber numberWithInt:100];

NSString *s = [NSString stringWithFormat:@"jack"];

NSString *s2 = @"rose";

 

0 0
原创粉丝点击