码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员---OC基础6【内存管理】【手动内存管理】【单、多个对象的内存管理】【*@property参数】【@class的使用】【NSString类的内存管理】【autorelease使用】

时间:2015-10-06 22:10:19      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:

------- iOS培训、Android培训、Java培训、期待与您交流! ----------

 

【内存管理】

1、内存管理概念

    由于移动设备内存及其有限,所以每个app所占的内存也是有限的

    需要回收一些不使用的空间

 

2、OC内存管理的范围

    管理任何继承NSOject的对象,对其他的基本数据类型无效

     技术分享

    主要管理堆区中的对象的内存管理

 

3、内存管理的原理

    1)对象所有权概念

      任何对象都可以能拥有一个或多个所有者,只要一个对象至少还拥有一个所有者,他就会继续存在

 

    cocoasu所有权策略

      任何自己创建的对象都归自己所有,可以使用名字以“alloc”或“new”开头或名字中包含“copy”的方法创建对象,可以使用retain来获得一个对象的所有权

    对象引用计数器

    对象的结构:

      3)引用计数器的作用

        引用计数器是判断对象要不要回收的依据(对象值为nuil时,引用计数为0,但不回收空间)就是计数器是否为0,若不为0则存在

      4)对引用计数器操作

        给对象发消息,进行和相应的计数器操作

        retain消息,使计数器+1,该方法返回对象本身

        release消息,使计数器-1(并不代表释放对象)

        retainCount消息,获得对象当前的引用计数器值  %ld   %tu

      5)对象的销毁

        当一个对象的引用计数器为0,那么它将被销毁

        系统会自动向对象发送一条dealloc消息,相当于临终遗言;

        一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法)

        一旦对象被回收了,那么他所占的储存空间就不再可用,坚持使用会导致程序奔溃(野指针)

    注意:

    1)如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序程序退出)

    2)任何对象,刚创建的时候引用计数器为1,当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1

 

4、OC内存管理分类

    三种内存管理方法

      1)MRC 手动管理,需要自己控制

      2)ARC 自动引用计数(系统默认的模式)

      3)垃圾回收(ios不支持垃圾回收)

      实际使用时尽量用ARC

 

【手动内存管理】

 

 1 1、关闭ARC的方法
 2     1)设置项目类信息
 3     //dealloc方法,是对象的临终遗言
 4     //对象被销毁时会自动调用该方法
 5     //注意:dealloc方法是系统自动调用的,不需要手动调用
 6     -(void)dealloc{
 7     //    先释放子类自己的对象空间
 8         NSLog(@"已经销毁");
 9     //    再释放父类的
10         [super dealloc];
11     }
12     
13     #import <Foundation/Foundation.h>
14     #import "Person.h"
15     int main(int argc, const char * argv[]) {
16         @autoreleasepool {
17     //        用person类实例化一个实例对象
18             Person * p = [Person new];
19     //        证明有一个所有者
20             NSLog(@"%ld",[p retainCount]);//1
21     //        使用引用机器数+1
22     //        调用两次
23             [p retain];
24             NSLog(@"%ld",[p retainCount]);
25     //        回收对象
26             [p release];
27             NSLog(@"%ld",[p retainCount]);
28             [p release];//此处执行后,p的空间被回收0
29             
30     //        NSLog(@"%ld",[p retainCount]);
31     //        证明p的空间被释放,可以在person类中,重写dealloc方法
32         }
33         return 0;
34 }

 

1、内存管理原则

1)原则

只要还有人在使用对象。那么这个对象就不会被回收

只要你想使用这个对象,那么就应该让这个对象的引用计数器+1

当你不想使用这个对象,应该让对象的引用计数器-1

 

2)谁创建,谁release

1)如果你通过alloc、new、copy来创建了一个对象,那么你就必须调用release或者autor

2)不是你创建你就不用去负责

3)谁retain谁release

只要你调用了retain,无论这个对象如何生成,你都要release

 

4)有始有终,有加就要有减

 

2、内存管理研究内容

1)野指针:

1)定义的指针变量没有初始化

2)指向的空间已经被释放

2)内存泄露

{

Person * p = [Person new];

 

}

p栈区

[Person new] 堆区

如果栈区的已经被释放了,而堆区的空间还没有释放,堆区的空间就被泄露了

 

 

【单、多个对象的内存管理】

 

1、单个对象的野指针问题

    如果一个对象已经被释放了,就是一个僵尸对象

     //这句化默认不报错,已经释放了是一个僵尸对象,这个p已经是一个野指针了

    僵尸对象:所占用空间已经被回收的对象  

  注意:

    1)空指针,没有指向任何东西的指针,给空指针发信息不会报错  

    nil类的初始化

    【NSNull  null】是一个对象,用在不能使用nil的场合

    2)[p retain];不能使僵尸对象复生

    3)野指针操作

      已经释放不能再用指针访问方法

2、避免使用僵尸对象

    1)方法:

    释放对象后,给对象赋值为nil

      p   = nil;

    2)泄露情况:

      (1)创建完成,使用之后,没有release

      (2)没有遵守内存管理的原则,计数器没有归0;

      (3)不当的使用了nil,没有释放之前就给对象赋值为nil;

      (4)在方法中对传入的对象进行了retain

 

3、多个对象野指针问题(栈区指针还在,堆区已经释放了)

    一个人对象,一个车对象,车对象销毁后,人就无法调用车方法,野指针

 

4、多个对象的泄露问题(栈区指针回收,堆区空间未释放)

      多个对象,问题,可以嵌套销毁,在dealloc重写里面加上调用的对象销毁语句;

      car = nil;

      self .car  = nil

 

5、set方法的内存管理

      1 )-(void)setCar{

      if(_car !=csr){

        [_car release];

      [_car relain];

      }

    }

    2)如果是基本对象,直接赋值

    3)如果在一个类中,有其他类对象,关联关系,set方法书写,先release旧值,再retain新值,还要判断是否是同一个对象

 

【*@property参数】

 

1、*@property参数

    格式:@property(参数1,参数2)数据类型  方法名

     技术分享

    原子性:一件事情完成之前,另一件事情无法进行;

      retain中又if判断

      @property (nonatomic,retain) NSString *picture;

      @interface Dog : NSObject

      @property (nonatomic,readwrite,assign) int age;

      @end

    1)多线程管理

      用默认的atomic

    2)set方法名替换

      @property (setter=isVip:,getter=isVip) int age;

 

【@class的使用

 

1、@class使用

      //#import作用:

      //把要引用的头文件的内容,拷贝到写#import处

      //如果Goods.h头文件内容发生变化了,此时所有引用了头文件的都要重新编译

      #import "Goods.h"

      @class Goods;

      @class可以简单的引用一个类

      使用格式:@class  类名;

      @class  xxx

      含义:告诉编译器,xxxx是一个类,至于类有哪些属性和方法,此处不去检测、

      好处:如果xxxx文件内容发生了改变,而不需要重新编译

         简单便捷,效率高

      缺点:只是告诉编译器有一个类,但是并没有去检查里面的方法,不能直接调用

      解决方法:在使用的时候在.m文件中用#import引用头文件

       在运行的时候才在.m文件中进行检查,提高了效率;

    注意:

        1).h  @class  xx;

        2).m  #import xx.h;

 

2、@class可以解决循环引入问题

      A<->B互相引用,用@class可以解决,#import会报错

 

3、@class和#import区别

      1)作用上区别

      2)效率上区别

 

【NSString类的内存管理

 

1NSString类的内存管理

技术分享

 1  NSString *str1 = @"abc";//@"abc"字符串的常量
 2 
 3         
 4 
 5         NSString *str2 = [NSString stringWithFormat:@"aaa"];//不是在栈区,在堆区
 6 
 7         //常量区
 8 
 9         NSString *str3 = [NSString stringWithString:@"abc"];
10 
11         //不是在栈区,在堆区
12 
13         NSString *str4 = [[NSString alloc]initWithFormat:@"aaa"];
14 
15         
16 
17         NSString *str5 = [[NSString alloc]initWithString:@"abc"];//常量区
18 
19         int a = 10;//栈区
20 
21         NSLog(@"%p",&a);
22 
23         NSLog(@"str1 = %@,%p,%lu",str1,str1,str1.retainCount);
24 
25         NSLog(@"str2 = %@,%p,%lu",str2,str2,str2.retainCount);
26 
27         NSLog(@"str3 = %@,%p,%lu",str3,str3,str3.retainCount);
28 
29         NSLog(@"str4 = %@,%p,%lu",str4,str4,str4.retainCount);
30 
31         NSLog(@"str5 = %@,%p,%lu",str5,str5,str5.retainCount);
32 
33     }
34 
35  

 

【autorelease使用】

1、自动释放池

自动释放池

1)在ios程序运行过程中,会创建很多自己释放池,是栈结构,先进后出

2)当一个对象调用autorelease时,会将这个对象放到位于栈顶得释放池中

 

自动释放方式

@autoreleasepool

{开始自动释放

 

 

}结束自动释放

它可以暂时的保存某个对象,然后再内存池自己的排干的时候对其中每一对象发送release信息,不一定释放,只是-1

 

2、使用@@autorelease好处

1)不需要关心对象释放的时间

2)不需要关系什么时候调用release

 

 


 

 

黑马程序员---OC基础6【内存管理】【手动内存管理】【单、多个对象的内存管理】【*@property参数】【@class的使用】【NSString类的内存管理】【autorelease使用】

标签:

原文地址:http://www.cnblogs.com/snowimba/p/4857803.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!