黑马程序员--iOS--Objective-C基础 (内存管理一)

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

1、内存管理

为什么要进行内存管理

移动设备的内存有限,APP的内存会被系统限制,当超出限制会发送消息给APP,此时就需要回收一些不使用的对象和变量,否则程序会崩溃或闪退。

内存管理的范围

管理任何继承NSObject的对象,对其他的数据类型无效。


对象类型是在程序运行过程中动态分配的,存储在堆区。内存管理主要是对堆区中对象的内存管理。

局部变量一般放在栈里面,栈空间存储的东西是自动回收的,代码块完毕后,里面的局部变量会被销毁,也就是一旦没有作用后,就会被系统回收。

2、内存管理的原理

1)对象的所有权和引用计数器

对象所有权:

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

在使用 alloc 、new、 copy init  创建对象,新对象的引用计数器默认就是一。 

2)对象的引用计数器

每个OC对象都有自己的引用计数器,是一个表示对象被引用的次数,计数器的值变为0时,则对象销毁。

                                   每个OC对象内部,都专门有8个字节的存储空间来引用计数器。

判断对象要不要回收的唯一依据是计数器是不是为0。为0则需要回收。

3)计数器的操作

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

      release消息:计数器-1,不代表释放了对象

      retainCount 消息:获得当前对象的引用计数器值    (%ld   %lu)

4)对象的销毁

对象被销毁时,会向系统发送一条  dealloc 消息,一般会重写dealloc方法,在这里释放相关的资源

一旦重写了 dealloc 方法就必须调用[super  dealloc],放在代码块的最后调用。

<span style="font-size:12px;">#import "Person.h"

@implementation Person

//注意:dealloc 方法是系统根据引用计数器的值,自动调用的,
//不需要手动调用
- (void)dealloc
{
    
    NSLog(@"Person类已经被回收内存空间");
   
    [super dealloc];
}
@end</span>

5)OC中的内存管理分为3类

     手动内存管理(MRC)

     自动内存管理(ARC)

     垃圾回收(iOS不支持垃圾回收)

     所以在开发中我们需要理解MRC,在实际使用尽量用ARC。

3、手动内存管理

      什么是内存泄漏

      内存泄漏也叫“存储渗漏”,是动态存储分配的内存空间,在使用完毕以后,未被释放,导致其一直占据内存空间。直到程序结束。

导致内存泄漏的可能情况:

<span style="font-size:12px;">        //单个对象的内存泄露问题
        //内存泄露情况1:
        // 创建完成 使用之后,没有release
//        Dog *d = [[Dog alloc] init];  //1
//        NSLog(@"%lu",d.retainCount);  //使用d对象
       
        //内存泄露情况2:
        //没有遵守内存管理的原则
//         Dog *d = [[Dog alloc] init];   //1
//         [d retain];  //2
//        [d release];
//         [d release]; //1
        
        //内存泄露的情况3:
        //不当的使用了nil
//        Dog *d = [[Dog alloc] init];   //1
//        d = nil;
//        
//        [d eat];  //nil eat
//        [d release]; // nil release
        
        //内存泄露的情况4:
        //在方法中对传入的对象进行了retain
        Dog *d = [[Dog alloc] init];  //1
        NSLog(@"d.retainCount = %lu",d.retainCount);
        //对象依然被泄露了
        [d compareColorWithOther:d];  //2
        NSLog(@"d.retainCount = %lu",d.retainCount);
        
        [d release];
</span>

set 方法的内存管理

1)基本数据类型

int   float  double   long  struct  enum 

-  (void)  setSpeed :(int) speed

{

          _speed = speed;

}

2)对象作为另外一个类的实例变量

-  (void) setDog : (Dog *)dog

{

     if (_dog != dog)  {

   [ _dog    release ];

_dog = [ dog retain ];

}

}

       @property 参数

  

4.4之后的增强型格式:

@property    (nonatomic , assign) int  age;

@property    (nonatomic , retain) Car * car;

一般在实例变量是基本数据类型的时候使用 assign 。

在一个类中关联另外一个对象的时候使用     retain 。

@class的使用

作用:简单的引用一个类,告诉编译器这是一个类,而类的方法和属性不会去重新检测

格式:@class  类名;

#import   #include  @class的区别

    #import  和#include  在大部分功能上都是一样的。都是可以引入文件。但是#import 解决了重复引用的问题。

    @class 则是声明了一个类,告诉编译器这是一个类,不用去现实,不去管类包含的属性和方法。

    #import和 #include 引入一个类会包含这个类的所有信息,这会影响编译器的效率。比如100个类都#import 了同一个类,在编译时这100个类都会对被引用这个进行处理。

自动释放池

1)在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构存在的

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

自动释放池的创建方式

 iOS5.0以后

 @autoreleasepool

   {//开始代表创建自动释放池


   }//结束代表销毁自动释放池

使用autorelease的好处

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

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

autorelease的基本用法

 1)创建自动释放池

@autoreleasepool

   {


   }

2)加入自动释放池(引用计数器不会发生变化)

     [ 对象   autorelease ]; 

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {//创建自动释放池
     
        Person  *p = [Person   new];
        
        [p  run];
        
        NSLog(@"p.retainCount = %lu",p.retainCount);
        
        [p  autorelease];//加入到自动释放池
        
        
    }//结束自动释放池
    return 0;
}

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值