OC 06内存管理

内存区域

 1.堆区:需要的时候系统会为你分配内存,但是系统不会自动回收,需要程序员手动释放内存

 2.栈区:需要的时候系统会为你分配内存,不需要的时候系统自动回收该内存

 3.常量区:存储常量,数据不能修改

 4.全局,静态区域:存储全局变量和静态变量

 5.自由存储区

 

内存管理的原理

   保证每个对象在使用的时候存在于内存中,不用的对象在最后从内存中清除。

一个对象的生命周期:

  1.对象的初始化

  2.执行,使用

  3.释放

 

   对象使用内存结束后,需要释放自身所占的资源,归还给系统,以保证别的对象可以使用。

注意:内存管理只针对继承NSObject的对象,对其他的基本数据类型(int,float,double...)无效。

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

 

 

 

 retainCount

   在引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。

   1.每个OC对象都有自己的引用计数器,retainCount

   2.当对象被创建时,引用计数置为1(alloc、copy或则new),注意是置为1,不是加1

   3.使对象的引用计数+1,并且获得对象的所有权;

   4.使对象的引用计数-1,并且放弃对象的所有权;

   5.当引用计数值为0的时候,对象将被系统销毁。

 

那OC中,使用什么来控制对象的引用计数呢?

   retainCount:获取对象当前的引用计数值;

   alloc:返回一个对象,并将其引用计数设置为1,类方法;

   retain:将对象的引用计数加1;

   release:将对象的引用计数减1;

   autorelease:将对象加入自动释放池,对象引用计数滞后减1;

  除了上述方法之外,还有对象销毁的方法dealloc,我们不会主动调用,但是需要在类中重写;

//自动走,无需调用

-(void)dealloc

{

    NSLog(@"person dealloc");

    [_book release]; //self.book = nil;

    [_name release];

    [super dealloc];

}

 

多个对象的内存管理

.h文件中

#import<Foundation/Foundation.h>

#import"Book.h"

@interfacePerson : NSObject

{

    Book *_book;

    NSString *_name;

}

-(void)setBook:(Book *)book;

-(Book *)book;

 

   .m文件中

-(void)setBook:(Book *)book

{   //判断旧的和新的是否是同一个

    if(_book != book){

    //释放旧的

    [_book release];

    //持有新的

    _book = [book retain];

    }

}

-(Book *)book

{

    return _book;

}

 

main.m文件中

//某个人拥有一本书

        Person *person = [[Person alloc]init];

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

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

        person.book = myBook;  //要获取新的对象,引用计数要为2,所以在set方法中写

        person.book = myBook1;

        [person release];

        [myBook release];

 

自定义初始化方法

.h文件中

-(instancetype)initWithBook:(Book *)book name:(NSString *)name;

.m文件中

-(instancetype)initWithBook:(Book *)book name:(NSString *)name

{

    self = [super init];

    if (self) {

        //因为是初始化,所以不需要在前面加release

        _book = [book retain];

        _name = [name retain];//对应的release在dealloc里面

       

    }

    return self;

}

 

集合

  1.某个对象,加入到数组中,retainCount + 1,不影响数组的retainCount

  2.数组的retainCount改变不影响数组里面的元素的retainCount

  3.数组对象被销毁,里面所有的对象元素,retainCount -1

   集合都是同理

   Person *person = [[Person alloc]init];

        NSArray *array = [[NSArrayalloc]initWithObjects:@"1",@"2",person, nil];

        NSLog(@"per = %lu,arr =%lu",person.retainCount,array.retainCount);

        [array retain];

        NSLog(@"per = %lu,arr =%lu",person.retainCount,array.retainCount);

        [array release];

        [array release]; //数组没有了,所有的元素都会release一次,所以person只需release一次

        [person release];

 

自动释放池

  NSAutoreleasePool:自动释放池类或对象

  类似于一个容器,所有加入容器中的对象都被他管理,在自动释放池,自身销毁的时候,池将会释放(release)所有的对象

  autorelease 方法把对象加入池中,一个对象可以被多次autorelease

  便利初始化的对象默认已经加入当前池中

      NSAutoreleasePool*pool = [[NSAutoreleasePool alloc] init];

       //pool 1

      Person *person = [[Person alloc]init];//1

      [person retain];//2

      NSLog(@"person = %ld",[personretainCount]);

      [person retain];//3

      NSLog(@"person = %ld",[personretainCount]);

      [person autorelease];//3

      NSLog(@"person = %ld",[personretainCount]);

      [person autorelease];//3

      NSLog(@"person = %ld",[personretainCount]);

      [person autorelease];//3

      NSLog(@"person = %ld",[person retainCount]);

      [pool release]; //person = 0(1)

NSLog(@"person =%ld",[person retainCount]);

 

便利构造方法

NSArray*array = [[[NSArray alloc]initWithObjects:@"1", nil]autorelease];

    //等价于上面的alloc+autorelease,系统的便利构造方法不需要内存管理

   NSArray * array1 = [NSArrayarrayWithObjects:@"2", nil];

自定义便利构造法

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

    Person*person = [Person PersonWithBook:book name:@"lili"];

[book release];

属性的内存管理

@property (nonatomic,retain)Book*book;  //用属性就不用再进行set方法重写的内存管理,重写dealloc就行了

 

循环引用

//让其中一个属性变为弱引用,在相互导入的时候,最好用@classPerson,如果要使用类中的属性和方法,需要在.m导入#import

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

 Person *person = [Person PersonWithBook:book name:@"lili"];

 person.book = book;

 book.person = person;

 [book release];

//在ARC状态下,如果是对象类型 retain,copy – strong

//weak

//MRC状态下,不需要持有对象  assign ,需要持有对象 retain,copy

  NSString *string = @"hello";

 NSLog(@"%ld",string.retainCount);

 NSString *string1 = [[NSString alloc]initWithFormat:@"你好"];

 [string release]; //建议写

 NSLog(@"string1 = %ld",string1.retainCount);

 

异常状况

//1、混乱释放

  Person * person = [[Person alloc] init];

  Person * person1 = person;

  [person1 release];//不遵守内存管理原则     

  [person release] 较标准

 

 //2、内存泄露

   Person * person1 = [[Person alloc] init];

   Person * person2 = [[Person alloc] init];

   person2 = person1;//指针指向发生改变,person2原有内存 泄露, 解决方案 autorelease

 

 //3、过度释放

    Person * person = [Person personWithName:@"tom" age:12];

    [person release];//便利构造器初始化的对象,过度释放了,不需要release

 

 //4、nil对象的引用计数为0

    Person * person = nil;

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

 

 //5、常量对象的引用计数为无穷

   NSString * name = @"name";

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

  //name对象放在常量区

 

//6.针对NSString对象

  NSString *string = [[NSString alloc] initWithFormat:@"213"];

  NSLog(@"string = %ld",[string retainCount]);

  //在堆中分配内存,都用引用计数模式,该string对象是常量区,用%d打印是-1,%lu就是正无穷

   NSMutableString *mutableString = [[NSMutableString alloc]initWithFormat:@"111"];

   NSLog(@"mutalbe = %ld",[mutableString retainCount]);

//nsmutableString创建的对象,是在堆中分配内存的,遵循引用计数模式

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值