iOS开发之OC内存管理

1、内存管理原因:

    (1)内存溢出   内存不够用
    (2)野指针异常   指针操作了不属于自己的存储空间,指针操作已经销毁的对象

2、内存管理的方式

    (1)垃圾回收  OC支持,mac开发支持,iOS开发不支持
    (2)mrc  iOS开发  手动操作引用计数,手动调用控制引用计数的方法
    (3)arc  iOS开发  自动操作引用计数,编译器调用引用计数的方法

3、内存管理的机制

    (1)引用计数   标记程序运行期间,对象被引用的次数
    (2)通过操作引用计数,控制对象是否被销毁。
    (3)当引用计数应该减为0时,对象自动被销毁,存储空间被回收

4、操作引用计数的方法

    (1)造成引用计数增加

    alloc   当前对象  0 -> 1
    retain  当前对象  加1
    copy    原来的对象 不变   新的对象  0 -> 1

    (2)造成引用计数减少

    release  当前对象  立即减1
    autorelease   当前对象  延迟减1  非立即

5、销毁对象

    dealloc  引用计数将要减为0时,对象自动调用

    (1)继承自NSObject,可以不实现,编译器默认实现
    (2)如果实现dealloc方法
- (void)dealloc
//当对象的引用计数应该减为0时,对象自动调用dealloc方法,销毁对象,释放内存空间

{

    NSLog(@"Person对象被销毁");
    [super dealloc];//这句代码写在dealloc方法实现的最后一步
}

引用计数

     Person * p = [[Person alloc]init];
       NSLog(@"%lu",p.retainCount );
           [p retain];
        NSLog(@"%lu",p.retainCount);

        //指针p2指向Person对象,此时引用计数没有任何变化
        Person * p2 = p;

        //p2指向的Person对象,引用计数加1
        //指针p3指向p,p2 指向的Person对象
        Person * p3 = [p2 retain];

        //打印引用计数
        NSLog(@"%lu",p.retainCount);
        NSLog(@"%lu",p2.retainCount);
        NSLog(@"%lu",p3.retainCount);


        //调用release,实现引用计数减1
        [p release];
        NSLog(@"%lu",p.retainCount);
        [p release];
        NSLog(@"%lu",p.retainCount);

        //当引用计数应该减为0时,对象被销毁,存储空间被回收
        //对象被销毁后,打印引用计数显示结果为1
        [p release];
        NSLog(@"%lu",p.retainCount);//应该减为0

        //retainCount的作用:观察引用计数的变化,增加减少的变化
        //不能使用上面创建的Person对象,已经被销毁

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

        [pe1 retain];//2

        [pe1 autorelease];//未来某个时刻引用计数减1

        NSLog(@"%lu",pe1 .retainCount);//2

autorelease
1、创建自动释放池对象
2、在自动释放池内,对 对象进行autorelease操作。
3、自动释放池会记录对象(如果同一个对象,两次调用autorelease,该对象会被记录两次)
4、当自动释放池销毁时,记录的所有对象,依次调用release方法
1)第一种写法

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];  
        Person *p = [[Person alloc ] init   ];//1

        p.name = @"yihuiyun";

        [p retain];//2

        [p retain];//3

        [ p autorelease];//3
        NSLog(@"%lu",p.retainCount);

        [ p autorelease];//3
        NSLog(@"%lu",p.retainCount);

        //销毁自动释放池

        [pool release];//销毁
      //  [pool drain];清空

        NSLog(@"%lu",p.retainCount);

2)第二种写法


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

        [pe retain];
        NSLog(@"--%lu",pe.retainCount);

        @autoreleasepool{

        [pe autorelease];
        NSLog(@"--%lu",pe.retainCount);

        }

        NSLog(@"--%lu",pe.retainCount);
 //pe指向的对象的引用计数为1
//在这个位置:
//如果只写一句[pe release];对象正常被销毁,不存在内存问题
 //如果不写[pe release];main函数运行结束后,局部变量pe被销毁,没有指针指向对象,造成内存泄露
//如果写了不止一句[pe release]; 过度释放,本质野指针异常

mrc支持两种写法,ARC只支持第二种

//深拷贝、浅拷贝
        //深拷贝:拷贝的是对象,创建了新的对象
        //浅拷贝:拷贝的是指针,操作的是原来的对象,没有创建新的对象

        //Person类实现的深拷贝

        Person *p1 = [[Person alloc ]init];
        p1.name = @"yihui";

        Person * p2 = [p1 copy];
        NSLog(@"%@",p2.name);

        NSLog(@"%@ %@",p1,p2);
        NSLog(@"%lu %lu",p1.retainCount,p2.retainCount);

        //Studnet类的浅拷贝

        Student *s1 = [[Student alloc]init];
        s1 .name = @"wu";

        Person * s2 = [s1 copy];
        NSLog(@"%@",s2.name);

        NSLog(@"%@ %@",s1,s2);
        NSLog(@"%lu %lu",s1.retainCount,s2.retainCount);



        //字符串的retainCount
        //常量字符串对象,retaincount是最大值
        NSString *str1 = @"yihuiyun";
        NSLog(@"str1 %lu",str1.retainCount);//1844...
       // NSLog(@"str1 %d",str1.retainCount);//结果为-1(常量区)

        NSString * str2 = [[NSString alloc]initWithFormat:@"yihuiyun"];
        NSLog(@"str2 %lu",str2.retainCount  );//打印结果1(堆区)

        NSString *str3 = [[NSString alloc]initWithFormat:@"123"];
        NSLog(@"str3 %lu",str3.retainCount);

        //字符串类的initWithFormat方法创建的对象,可以在堆区或常量区
        //内存管理只参考内存管理原则,即影响引用计数的5个方法





        //NSString类型的对象,调用copy得到的结果
        NSString * str4 = [[NSString alloc]initWithFormat:@"你大舅你二舅都是你舅"];
        NSString * str5 = [str4 copy];
        NSLog(@"%p,%p",str4,str5);
        NSLog(@"%lu",str5.retainCount);

        [str4 release];
        [str5 release];


        //copy 和MutableCopy

        //对象调用copy方法,得到的是不可变的对象
        //对象调用MutableCopy,得到的是可变的对象

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

        NSMutableArray * array2 = [array1 mutableCopy];

        [array2 addObject:@"4"];

        NSLog(@"array2 = %@",array2);

//copy方法的实现
- (id)copyWithZone:(NSZone *)zone
{
   // Person * p  = [[Person allocWithZone:zone]init];以前的iOS版本需要这样写,如果需要向下兼容,可以写这句代码

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

    p.name = self.name;//self表示调用copy方法的对象,即被拷贝的对象

    p.age = self.age;
    return p;

}

//便利构造器内部实现了创建对象,使用autorelease造成对象被销毁
//使用便利构造器创建的对象,不能再使用release
//便利构造器创建的对象,被销毁的时间未知(在一段代码内,如果控制便利//构造器创建的对象的自动释放池未销毁,则对象暂时可以安全使用)
        Person * p1  = [Person personWithName:@"wu"];


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值