详解ARC

详解ARC

  • 从C理解引用计数器
  • ARC的演变历程
  • OC中的ARC

长达三个多月的项目,改了无数次版,到最后出来的产品和原先定义的完全不同。一直没有时间去好好的总结下。作为一枚程序员,只有不停的学习才能保持很好的学习状态。我学习一样东西很喜欢究根究底,可能是生性愚笨,就安慰自己勤能补拙吧。关于ARC我相信大家都深有了解了。可是面试的时候仍然有些问题卡壳,记得不够牢或者是理解得不够深刻。那么下面我将从C引出OC中的ARC,希望对大家能有帮助。也让我自己完完全全的掌握它。

作为第一篇博客,可能排版不太好看,多多谅解


1.从C理解内存管理


首先创建一个简易的C语言工程 OS X –>Application –>Command Line Tool

要使用C中手动分配内存要添加头文件#include <stdlib.h>

手动分配的内存在堆中。C语言项目比较OC来说更加繁琐,因为底层代码实现一个功能需要的代码量更多,往往一个项目组需要十几个人,所以当我们手动去管理内存的时候,A创建对象,B要使用,A并不知道B什么时候去使用内存,自己创建自己释放、A.B都要对方释放、A、B都以为对方没有释放,自己释放、等情况会造成以下内存问题:

  1. 内存提前释放
  2. 内存泄露
  3. 内存多次释放

就会造成程序崩溃。

#include <stdio.h>
#include <stdlib.h>

void test(int *p)
{
    printf("调用了test方法\n");
    free(p);
}

int main(int argc, const char * argv[]) {

    int *p = malloc(4);
    test(p);
    free(p);
    test(p);

    return 0;
}

在上面代码块中,通过两次free(p)我已经释放掉了P,但是我在释放掉了p后仍然调用了这块内存,毫无疑问,会导致崩溃

这里写图片描述

那么我们如何精准的知道什么时候去释放p这块内存呢?

当p的引用次数为1的时候,我们就应该去调用free(p)了。那么我们需要其他成员在使用p时,将p的引用次数加一,使用完后减一,我们在判断当引用计数为1的时候,去调用free方法。这样就会避免上面三种内存问题。

那么我们需要一个值count来记录p的引用次数。

#include <stdio.h>
#include <stdlib.h>

int count = 0;

void release(int *p)
{
    if (count>1) {
        count--;
    }else
    {
        free(p);
    }
}

void test(int *p)
{
    count ++;
    printf("调用了test方法\n");
    release(p);
}

int main(int argc, const char * argv[]) {

    int *p = malloc(4);
    count = 1;//创建p时 p的引用次数为1
    test(p);
    test(p);
    test(p);
    release(p);
    return 0;
}

那么无论项目中的成员什么时候去调用p时,都不会产生内存问题。

那么又存在一个问题。当我们对象足够多的时候,如何做到对象和它的引用计数绑定呢?大家可能第一反应是字典,可是C中没有字典啊。 利用结构体可以解决这个问题,OC中一个对象自带的retainCount实现原理也就是这样。


2.ARC的演变历程


这部分参考以下链接,大家可以看下大神的解说。

唐巧->理解iOS内存管理

自动引用计数(Automatic Reference Count,简称ARC),是苹果在WWDC(Worldwide Developers Conference)2011年大会上提出的用于内存管理的计数,所以11年以后接触iOS开发的可能无法理解前辈们使用MRC来管理内存的痛苦。即使是高级的iOS开发者也无法一次性的管理好内存。

有个面试经常问到的问题:使用ARC后,完全不用自己管理内存了吗?

如果对ARC了解不够或者一直以来依赖于ARC来管理内存的开发者来说可能回答的支支吾吾,那么面试官一下就能知道你的水平如何了。

【就算使用ARC后,仍然有两部分是需要我们手动管理内存的:block块的使用和core foundation的使用】这里不做详述

不管你是【前辈】还是【小白】,能够正确使用ARC和MRC,发挥ARC的作用,同时也要掌握MRC,这样才能完全管理好内存。

3.OC中的ARC

如果是创建简单的Command Line tool 选择OC语言,在project 中的Build Settings 里面设置 OC ARC为NO

这里写图片描述

如果是创建Single View Application工程,我们则需要修改下参数,如果在AppDelegate.m中使用MRC,如下设置:Targets–>Build Phases–>AppDeleagte 添加-fno-objc-arc 编译参数:

这里写图片描述

接下来以工程为例 来进一步了解MRC

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    NSObject *object = [[NSObject alloc]init];

    NSLog( @" object.retainCount is %ld",[object retainCount]);

    [object release];

    NSLog( @" object.retainCount is %ld",[object retainCount]);


    return YES;
}

两次输出的retainCount 都为1,可能有人觉得困惑了 ,应该是1、0. 首先在object对象内存已经被回收的情况下,我们不能再去使用object,这种做法本身就是错误的,其次在第二次打印object的引用计数时,[object release]中系统已经知道要回收object对象了,就没有必要将retainCount再去减一,一个对象被回收后,它所有的内存空间就会变得没有意义,而且不将这个值从1变成0,还减少了一次系统的操作。加速对象的回收

OC中常见的ARC问题还有循环引用
对象A和对象B相互引用对方作为自己的成员变量,只有依赖对方才能将自己销毁,这样导致了循环引用的问题。解决办法:

  • 自己主动断开引用
  • 使用弱引用(引用对象,但是不使对象的成员变量加一,常见在delegate模式中).ARC:一端使用strong,一端使用weak、MRC:一端使用assign,一端使用retain

补充:黄金法则
凡是alloc.retain,copy,mutableCopy就要对应使用release或者autorelease。
希望大家能多提意见,有问题和有疑问的地方在下面评论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值