oc-内存管理

内存管理

内存管理的核心思想:谁分配 谁释放

分配在栈里的数据 不用程序员管理 系统管理

分配在堆里面的数据 需要程序员管理

NSString 、NSArray、NSDictionary 是继承父类的类方法创建的管理,已经加入到自动释放池了,不用我们管理

通过引用计数来判断是否需要销毁这个对象,为零时销毁这个对象。

引用计数加+1(alloc new copy retain)———引用计数减-1(release  autorelease)。

1.自动释放池

写在自动释放池生命周期以内的 带有延迟释放的对象都会在释放池生命周期结束后释放

              a.老:NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

                                           内容

                                   Person *p1 = [[Person new]autorelease];

                                   Person *p2 = [[Person new]autorelease];

                        [pool release];

               b.新:@autoreleasepool {

 

                   Person *p2 = [[Person new]autorelease];

 

                         }

该程序中初始化了同样的两个P2 但是运行没有出错,因为他们的生命周期都再花括号内。

 

2.拷贝

retain和copy的区别

retain是给原来对象的引用计数+1;

copy会生成一个新的对象 给新的对象引用计数+1

Person *person = [Person new];

Person *person1= [person copy];

   a.自定义拷贝:除了字符串、字典、NSNumber,数组,都需要自定义拷贝的功能(遵守拷贝协议)

   b.深浅拷贝:

                深拷贝:完全拷贝一个对象,这个对象与原来的对象 完全是两个个体

        

               签拷贝:只拷贝对象本身 不拷贝对象里面的内容

      判断深浅拷贝的依据:看他们(不止对象本身 也包含对象里面具体的内容)的内存地址是否一样,一样就是浅拷贝。

例子:

需要自定义的:

Penson.h文件有两个属性

           //属性内存管理

@property (nonatomic, retain)NSMutableArray  list;

@property (nonatomic, assign)int age;

//除了基本数据类型都用retain;

//nonatomic 非原子性 在多线程的情况下 不保证在不同线程不同数据的安全

//atomic 原子性 在多线程里面 保证数据的安全

//assign :基本数据类型使用 assign;

 

//ARC的情况下

//如果这个对象 在内存不足的时候 允许他被销毁掉 用unsafe_unretainde

//如果这个对象 在内存不足的时候 不允许他被销毁掉 用strong;

 

Penson.m文件中 (需要自定义拷贝)

 

-(id)copyWithZone:(NSZone *)zone{

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

    

    copyPerson.list = self.list ;

    copyPerson.age = self.age;

    

    return copyPerson;

}

 

 

- (id)mutableCopyWithZone:(NSZone *)zone{

    Person *copyPerson = [[Person allocWithZone:zone]init];

    copyPerson.list = [self.list mutableCopy];

    copyPerson.age = self.age ;

    return copyPerson;

}

 

 

在主文件中实现

Person *person = [Person new];

        Person *p2 = [person mutableCopy];

        NSLog(@"之前%p",person);

        NSLog(@"之后%p",p2);

        [p2 release];

        [person release];

结果:地址不一样 

 

 

 

 Person *person = [Person new];

        Person *p2 = [person copy];

        NSLog(@"之前%p",person);

        NSLog(@"之后%p",p2);

        [p2 release];

        [person release];

结果:地址一样

 

不需要自定义的:

例子:

数组实现深拷贝copyiItems 如果设置成YES就是深拷贝

NSDictionary *dic = @{@"dd":person};

        NSDictionary *di = [[NSDictionary alloc]initWithDictionary:dic copyItems:YES];

        NSLog(@"dic拷贝之前%p",dic[@"dd"]);

        NSLog(@“dic拷贝之后%p",di[@"dd"]);

字典也是一样了。。。。

 

容易出错的地方:

// 如果想让一个不可变对象 变成可变对象 可以使用mutableCopy

        

        NSArray *arr = @[@"1",@"2",@"3"];

        NSMutableArray *arrrr = [arr mutableCopy];

        

        [arrrr removeObject:@"2"];

        NSLog(@"%@",arrrr);

        

//        一个可变的对象 进行copy 它将变成一个不可变的对象

        NSMutableString *string = [NSMutableString stringWithString:@"dgadgg"];

        NSMutableString *sr = [string copy];

        [sr appendString:@"dgasdg"];

        NSLog(@"%@",sr);

这样就出现了错误哦!!!!!

 

原文地址:https://www.cnblogs.com/chenhongios/p/4605747.html