内存管理高级

 

OC内存管理

一、基本原理

    (一)为什么要进行内存管理。

由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等。

管理范围:任何继承NSObject的对象,对其他的基本数据类型无效。

本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对象已经没有指针指向,但依然存在于内存中,造成内存泄露。

 

(二)对象的基本结构

每个OC对象都有自己的引用计数器,是一个整数,表示对象被引用的次数,即现在有多少东西在使用这个对象。对象刚被创建时,默认计数器值为1,当计数器的值变为0时(原理就是你不引用它了,所以才把它释放掉,如果你还引用他,你释放了就会造成野指针),系统自动调用dealloc方法回收对象空间(一般会重写dealloc方法),在空间回收之前,将保有的其他对象的所有权给释放掉,例子见下:

-(void)dealloc

{

    当该类对象的引用计数为0,会自动调用该类的dealloc方法

    当调用dealloc方法时,该对象A的空间将要被系统回收,在空间回收之前,将该对象保有的对象B的所有权给释放掉

    [_tea release];//_tea指向的那个对象B的引用计数减1,因为对象A已经被回收,_tea也被回收了,它已经不会对B有所有权了.

    [super dealloc];

}

在每个OC对象内部,都专门有4个字节的存储空间来存储引用计数器(变量)。


(三)内存管理原则

如果你对一个对象进行alloc,retain,copy之后,你就拥有了该对象的所有权,你就必须对它进行release或者autorelease

(1)原则

只要还有人在使用某个对象,那么这个对象就不会被回收;

只要你想使用这个对象,那么就应该让这个对象的引用计数器+1

当你不想使用这个对象时,应该让对象的引用计数器-1

(2)谁创建,谁release

1如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法

2不是你创建的就不用你去负责

(3)谁retain,谁release

只要你调用了retain,无论这个对象时如何生成的,你都要调用release

(四)总结

有始有终,有加就应该有减。曾经让某个对象计数器加1,就应该让其在最后-1.


 

(四)@property的参数

(1)内存管理相关参数

Retain:对对象release旧值,retain新值(适用于OC对象类型)

Assign:直接赋值(默认,适用于非oc对象类型)

Copy:release旧值,copy新值

 

(2)是否要生成set方法(若为只读属性,则不生成)

Readonly:只读,只会生成getter的声明和实现

Readwrite:默认的,同时生成settergetter的声明和实现

(三)引用计数器的作用

判断对象要不要回收的唯一依据就是计数器是否为0,为0则回收



- (void)setTea:(Teacher *)tea

{

    //self.tea = tea;

    //[self setTea:tea];等价会造成死循环

    //判断原有对象和新对象是否是同一个,如果是同一个就没有必要在重新赋值了,否则会先release,release之后空间被系统回收,此时在retain就成为野指针问题了

    if (_tea != tea) {

        [_tea release];//释放之前对象保有的所有权

        //让实例变量_tea 保有新的所有权

        _tea = [tea retain];

        }

    

}

-(Teacher *)tea

{

    return [[_tea retain]autorelease];

}

//语义特性声明为copy,setter方法内部实现

-(void)setTea1:(Teacher *)tea1

{

    if (_tea1 != tea1) {

        [_tea1 release];

        //如果相对一个对象进行copy操作,对象的类必须服从一个NSCopy协议,并且实现协议的方法

@interface Teacher : NSObject<NSCopying>

        _tea1 = [tea1 copy];

    }

}

-(void)dealloc

{

    

    [_tea release];

    [super dealloc];


}

- (id)copyWithZone:(NSZone *)zone

{

    Teacher *newTea = [[Teacher allocWithZone:zone]init];

    newTea.name = self.name;

    newTea.gender = self.gender;

    return newTea;

}

-(id)initWithName:(NSString *)name gender:(NSString *)gender

{

    if (self = [super init]) {

        self.name = name;//使用setter方法retain下对所有权先保留一份

        self.gender = gender;

    }

    return self;

}

+(id)teacherWithName:(NSString *)name gender:(NSString *)gender

{

    Teacher *teacher =  [[Teacher alloc]initWithName:name gender:gender];

    //[teacher release];

    return [teacher autorelease];有alloc,有autorelease

}

-(void)dealloc

{

    [_name release];

    [_gender release];

    NSLog(@"回收了");

    [super dealloc];

}





        

  

        //便利构造器内存管理

//        Teacher *tea = [Teacher teacherWithName:@"Frank" gender:@"man"];

//        NSLog(@"%lu",[tea retainCount]);

//        NSLog(@"fan");

        

        //collection 的内存管理

       Teacher *tea1 = [[Teacheralloc]initWithName:@"xaiogaung"gender:@"man"];

       //0 -> 1

       Teacher *tea2= [[Teacheralloc]initWithName:@"xaiomeng"gender:@"man"];

       //0 -> 1

       Teacher *tea3 = [[Teacheralloc]initWithName:@"xaiojian"gender:@"man"];

       //0 -> 1

        //NSMutableArray *arr = [NSMutableArray arrayWithObjects:tea1,tea2,tea3, nil];

       NSMutableArray *arr = [[NSMutableArrayalloc]initWithObjects:tea1,tea2,tea3,nil];

       //挡把一个对象放入集合中(数组,字典,集合)中时,会将对象的引用计数加1,因为内部做了retain操作

       NSLog(@"%lu",[tea1retainCount]);

       NSLog(@"%lu",[tea2retainCount]);

        [tea1release];

        [tea2release];

        //[arr release];

   //2.collection(数组,字典,集合),空间被回收时,他们会向容器中的每一个元素都发送一个release消息(对应添加元素时的retain操作)

    

    //3.当从collection(数组,字典,集合)中移除一个元素时,release该对象,引用计数减1

    [arr removeAllObjects];

    [arrrelease];


//setter以及 getter方法,内不是对实例变量赋值以及实例变量的取值操作,所以方法没要操作实例变量



 


 


 


 


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值