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 }
  • 相关阅读:
    试图运行项目时出错,无法启动调试。没有正确安装调试器(转帖)
    IIS 401.2
    windows 2008 r2 64位运行crystal 2008的问题
    .net 命令行
    crystal report 2008 公式字段问题
    vs2003在IE8下无法调试的解决办法 (包括win2008 64位)
    Oninit里不能用ViewState
    web 开发的一些软件
    silverlight toolkit
    SqlConnection.Open的一些问题
  • 原文地址:https://www.cnblogs.com/ChinaKingKong/p/4640979.html
Copyright © 2011-2022 走看看