• 内存管理-MRC与ARC详解


    Objective-C提供了两种内存管理机制MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),为Objective-C提供了内存的手动和自动管理。下面我们来讲解MRC和ARC的基本概念以及自己的理解,欢迎大家指正!!!

    一、前言

    在讲述MRC和ARC之前,我们先来看一下Objective-C的引用计数式的内存管理方式。下面是一些特点:

    1. 自己生成的对象,自己持有。(通过alloc/new/copy/mutableCopy等方法)例如:NSObject *obj = [[NSObject alloc]init];
    2. 不是(非)自己生成的对象,自己也能持有:NSMutableArray *array = [NSMutableArray array];
    3. 无法释放非自己持有的对象

    1.自己生成的对象,自己持有

    在iOS内存管理中,有四个这样的关键字:new、alloc、copy、mutableCopy,如果自身使用这些关键字的时候来产生对象,那么创建完之后,自身也就有了对象。

        // 使用了alloc分配了内存,obj指向了对象,该对象本身引用计数为1,不需要retain 
        id obj = [[NSObject alloc] init]; 
        // 使用了new分配了内存,objc指向了对象,该对象本身引用计数为1,不需要retain 
        id obj = [NSObject new];

    2.非自己生成的对象,自己也能持有

        // NSMutableArray通过类方法array产生了对象(并没有使用alloc、new、copy、mutableCopt来产生对象),因此该对象不属于obj自身产生的
        // 因此,需要使用retain方法让对象计数器+1,从而obj可以持有该对象(尽管该对象不是他             产生的)
        id obj = [NSMutableArray array];
        [obj retain];     

    3.无法释放非自己持有的对象

     // 释放一个不属于自己的对象
        id obj = [NSMutableArray array]; 
         
     // obj没有进行retain操作而进行release操作,然后autoreleasePool也会对其进行一次release操作,导致奔溃。
      [obj release];

    针对[NSMutableArray array]方法取得对象方法,自己并不会持有对象,在底层是这样实现的

    + (id)object {
        //自己持有对象
        id obj = [[NSObject alloc]init];
         
        [obj autorelease];
         
        //取得的对象存在,但自己不持有对象
        return obj;
    }

    使用了autorelease方法,将obj对象注册到autoreleasePool中,不会立即释放,当pool结束时,再自动调用release。只有这样达到取得对象存在,而自己不持有对象。

    下面是来拓展一个问题:[className new]与[[className alloc] init]区别?

    面对区别,我么首先来看一下两个的源码。

    + new 
    { 
    id newObject = (*_alloc)((Class)self, 0); 
    Class metaClass = self->isa; 
    if (class_getVersion(metaClass) > 1) 
    return [newObject init]; 
    else 
    return newObject; 
    }
    
    
    
    //而 alloc/init 像这样: 
    + alloc 
    { 
    return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());  
    } 
    - init 
    { 
    return self; 
    } 

    通过上面的源码,我们可以发现[className new]与[[className alloc] init]基本是等同的。

    区别也在于alloc 分配内存的时候使用了zone方法。zone方法是给对象 分配内存的时候,把要关联的对象分配到一个相邻的内存区域,这样调用消耗很少的代码,提高了程序的处理速度。

    大家发现,如果使用new的时候,初始化方法就会被固定住,只能调用init,如果要想调用initXXX方法怎么办,这样就不行了。

    总结:采用new的方式只能通过默认的init方法完成初始化;采用alloc的方式可以使用其他的定制方法。

    MRC

    retain:作用是将内存数据被指向的一个指针变量,引用计数retainCount + 1

    release:作用是引用计数减1,也即是retainCount -1,

    autorelease:作用是将内存的管理放到autoreleasepool中去

    其中retain和release操作的是引用计数,当引用计数为0时,便会自动释放内存。

    //如果Number为预定义的类

    Number *num = [Number alloc]init;

    Number *num2 =  [num retain];//此时引用记数+1,现为2

    [num2 release];//num2为-1,现为1

    如果再次调用[num2 release]引用计数为0

     ARC

    在我们项目中,打开ARC的方式与关闭ARC的方式如下:

    选择Targets -> Compile Phases -> Compile

    • 打开ARC:-fobjc-arc
    • 关闭ARC:-fno-objc-arc

    ARC的修饰符

    Objective-C的ARC提供了__weak,__strong,__autoreleasing和__unsafe_unretained。下面我们一起看一下:

    __weak

    代表的弱引用,对象在被释放的时候,指向它的弱引用会自动被置为nil。这样可以防止野指针的产生,__weak也被用于delegate关系中防止循环引用。

    __strong

    代表的是强引用,如果在声明引用的时候,不加入修饰符,那么默认是强引用。

    __autoreleasing

    代表在autorelease pool中自动释放对象的引用,和MRC中的autorelease用法是一样的。但是需要注意一点:定义的property时不能使用这个修饰符,因为任何一个对象的property都不会是autorelease型的。

    __unsafe_unretained

    主要是针对iOS 4,现在已经退出了,大家可以不要深入了解。

    以上就是ARC与MRC的基本内容,希望对大家有所帮助。

    下一步将讲述MRC-block以及ARC-block的区别,继续探讨ARC与MRC。

  • 相关阅读:
    【数据库领域】mysql中in与or对比
    数据库优化
    数据库-索引
    数据库-事务
    数据库-视图
    数据库设计
    数据库编程提高
    数据库高级操作
    数据库基本操作
    with-上下文管理器
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/9480518.html
Copyright © 2020-2023  润新知