zoukankan      html  css  js  c++  java
  • iOS阶段学习第20天笔记(MRC内存管理)

    iOS学习(OC语言)知识点整理

     

    一、OC中的内存管理

    1)概念:内存管理的对象为所有继承了NSObject的对象,对基本数据(如:int 、float、double...)无效
          OC中采用引用计数器对内存做管理,他是一个整数数据,表示对象引用的次数,每个对象分配4字节
          的内存空间存放引用计数器当一个对象的引用计数器值为0时,它将被释放,反过来说,如果一个对象的
          引用计数器值不为0,这个对象永远不会被释放,除非程序退出。

    2) 当给对象发送一个retain消息,引用计数器值会+1,retain消息返回对象本身

    3)当给对象发送一个release消息,引用计数器值为-1.

    4)给对象发送一个retainCount消息,获取引用计数值
     
    5)当对象的引用计数器值为0,会被销毁,内存空间会被释放

    6) 当对象被销毁时,系统自动发送一个dealloc消息

    7)一般重写dealloc消息,释放相关资源,一旦重写dealloc方法,一定要调用[super dealloc];
          放在最后调用 不能直接调用dealloc方法

    8)OC中的内存管理分为:MRC(Manual Reference Counting)手动引用计数
          ARC:Automatic Reference Counting:自动引用计数。
     
    9)黄金法则 当使用alloc、new 、copy(mutableCopy)创建一个对象赋值给某个引用时后当不再使用这
          个引用时一定要发送release(autoRelease)消息 释放该对象所占用的内存。

    10)这里所讲的内存管理为手动内存管理,新建项目是系统默认是自动内存管理的,所以需要手动设置,即在项目
          的Build  Settings 中找到 Objective-C Automatic Reference Counting 项设置为NO; 同时需要添加对野指
          针的监控 即在Edit Scheme 中找到并勾选 Enable Zoombie Objects 项。

    11)内存管理操作 实例代码:

      1、添加一个Person类 .h文件中不做任何操作

      2、在.m 文件中析构系统销毁内存执行方法  例如: 

    1 #import "Person.h"
    2 @implementation Person
    3 //析构系统销毁内存执行方法
    4 -(void)dealloc{
    5      NSLog(@"Person dealloc");
    6 }
    7 @end 

      

    3、在main文件中执行操作 例如:

     1 Person *p1=[[Person alloc]init];//引用计数器默认+1
     2 [p1 retain]; //引用计数器+1
     3 
     4 NSLog(@"retainCount:%ld",p1.retainCount);//结果:2
     5 [p1 release];//引用计数器-1
     6 
     7 //retainCount 获取引用计数器的个数
     8 NSLog(@"retainCount:%ld",p1.retainCount);//结果:1
     9 [p1 release];p1=nil;//防止出现野指针,出现不安全因素 OC中可以给空指针对象发送消息
    10 NSLog(@"retainCount:%ld",p1.retainCount);//结果:0


    12)在使用组合类是销毁自身对象时需要先销毁组合的对象 ,即在析构方法中销毁组合对象 例如:

    1  //Person 类中有一个Book 类 在Person类的.m文件中添加此方法
    2    -(void)dealloc{
    3         [_book release];
    4        NSLog(@"Person dealloc");
    5     }


    13)组合类初始化时需要在父类中添加set方法用于在给组合类赋值时增加引用计数器个数 例如: 

    1     //Person 类中Book类的赋值方法
    2      -(void)setBook:(Book*)book{
    3        book=[book retain];
    4      }
    5 
    6      //Person 类中Book类的取值方法
    7       -(Book*)book{
    8           return _book;
    9      }

     
    14)数组中的内存管理:销毁数组对象时需要先销毁数组中存放的对象 例如:

     1 Book *b0=[[Book alloc]init];
     2 b0.ID=0;
     3 NSMutableArray *array=[[NSMutableArray alloc]initWithObjects:b0, nil];
     4 [b0 release];
     5  NSLog(@"%ld",b0.retainCount);
     6 for(int i=0;i<5;i++){
     7 Book *b=[[Book alloc]init];
     8 b.ID=i+1;
     9 NSLog(@"before,book:%ld",b.retainCount);
    10 [array addObject:b];
    11 NSLog(@"after,book:%ld",b.retainCount);
    12 [b release];
    13 NSLog(@"release,book:%ld",b.retainCount);
    14 }
    15 NSLog(@"%ld",array.retainCount);
    16 [array removeLastObject];
    17 NSLog(@"*******");
    18 [array release];

    15)数组对象中计数器的运行机制:

          1、当用对象创建数组时,数组会自动给对象的引用计数器+1

          2、将对象添加到数组时,数组会自动给对象的引用计数器+1

          3、将对象从数组中删除时,数组会自动给对象发送release,将引用计数器值-1

          4、当数组release时,会自动给所有的元素发送release消息

    16)循环引用的内存管理:针对循环引用时我们必须将其中一个对象类型由retain 改为assign 类型
           否则将无法彻底释放内存。


     17)循环引用时可能会出现头文件重复包含的问题 此时我们将#import  改为 @class  例如: @class Person; 


    18)autorelease 自动释放池 :将对象放入一个自动释放池中,当自动释放池被销毁时,会给池子中
          所有的对象发送 release消息autorelease 方法返回对象本身给对象发送autorelease 消息后引用
          计数器值不变

    19)创建自动释放池有2种方法:

    1 //方法一
    2 @autoreleasepool {}
    3 
    4 //方法二
    5 NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
    6 [pool release];

    20)autorelease好处:不用担心对象什么时候被释放;缺点:当对象很大时,不能精确控制对象的释放 ;能不用autorelease尽量不用.

    21)自动释放池 实例代码:

     1 @autoreleasepool {  //自动释放池的开始
     2 Book *b1=[[Book alloc]init];
     3 b1=[b1 autorelease];//返回对象本身
     4 NSLog(@"%ld",b1.retainCount);
     5 b1.ID=1;
     6 Book *b5=nil;
     7 @autoreleasepool {
     8 Book *b2=[[[Book alloc]init]autorelease];
     9 b2.ID=2;
    10  //[b2 release];//不能,已经有autorelease,在池子被销毁时再次发送release消息,就会出错
    11             
    12 //b5=[[[[Book alloc]init]autorelease]autorelease];
    13 //将同一个对象往自动释放池中放入2次,池子被销毁时会发送2次release消息,也会出现野指针错误
    14 b5=[[[Book alloc]init]autorelease];
    15 b5.ID=5;
    16 }
    17  //创建自动释放池方法二:
    18 NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
    19         
    20 [pool release];
    21 //NSLog(@"id:%d",b5.ID);
    22         
    23 Person *p1=[Person personWithAge:20];
    24 //p1不需要release,p1的创建没有alloc...关键字,已经在类方法中autoreleas过了
    25  //OC中有很多类提供了快速创建实例的类方法,都是autorelease的
    26         
    27 NSLog(@"*********");
    28 Student *stu=[Student personWithAge:29];
    29 stu.no=1001;
    30         
    31 }//自动释放池结束

    22)快速构建对象方法  例如: 

    1 +(id)personWithAge:(int)newAge
    2 {
    3 // p1对象的释放只能通过autorelease实现
    4 //子类继承后也可以用此方法快速创建子类的对象,需要使用self
    5 //(发送消息的引用,如果是父类就是Person,如果是子类就是Student)
    6 Person *p1=[[[self alloc]init]autorelease];
    7 p1.age=newAge;
    8 return p1;
    9 }
  • 相关阅读:
    POJ 3630 Phone List/POJ 1056 【字典树】
    HDU 1074 Doing Homework【状态压缩DP】
    POJ 1077 Eight【八数码问题】
    状态压缩 POJ 1185 炮兵阵地【状态压缩DP】
    POJ 1806 Manhattan 2025
    POJ 3667 Hotel【经典的线段树】
    状态压缩 POJ 3254 Corn Fields【dp 状态压缩】
    ZOJ 3468 Dice War【PD求概率】
    POJ 2479 Maximum sum【求两个不重叠的连续子串的最大和】
    POJ 3735 Training little cats【矩阵的快速求幂】
  • 原文地址:https://www.cnblogs.com/ChinaKingKong/p/4640979.html
Copyright © 2011-2022 走看看