iOS有关内存管理的二三事 原

iOS有关内存管理的二三事

一、前引

随着移动设备的内存越来越大,程序员也已经度过了为了那一两M的内存在系统的抽丝剥茧的年代,对于JAVA的开发者,对内存更是伸手即取,并且从不关心什么时候还回去。但是,程序的掌控度对程序员来说是至关重要的,任何语言的内存管理机制的初衷也是在有限的空间里完成最精致的逻辑。

二、Xcode工程设置ARC

ARC是xcode5中引入的自动引用计数,其原理与MRC是一样,只是系统帮助我们添加了retain和release。现在在xcode中新建的项目默认都是ARC的环境,我们可以通过设置其为MRC。

在BuildSettings中搜索ARC:

将下面的参数设置为NO,默认是YES。

这时项目工程的环境就变成了MRC。

三、项目中实现MRC和ARC混编

现实中的许多旧的项目,还有一些比较老的第三方库,可能都是采用MRC环境编写的,我们在对其进行扩展或者做新项目的兼容的时候,可以在xcode中对其进行混编。

选择:target->build phases->compile sources

如果工程是ARC,要混编MRC的文件,我们选中compiler flags,后面设置为-fno-objc-arc

如果工程是MRC,要混编ARC文件,我们在后面设置-fobjc-arc

四、IOS内存管理机制基本原理

无论你是只注重于代码逻辑,将内存交给ARC的新时代程序员,还是依然对apple的信任不足,依然事必躬亲的MRC古板程序员,我想你都应该了解IOS中内存管理的机制,尽管ARC机制很成熟也很可靠,可是依然会有很多应用存在循环应用,内存泄露等问题,要知道,ARC不是万能的,它仅仅只是帮你省去写一些繁琐的代码。

首先,在Object-C中创建对象返回的并不是对象本身,而是一个指针。比如我们使用alloc申请空间,会经常这样做:

UIImage * image = [[UIImage alloc]init];

这里,调用的alloc时,系统将给我们创建的类分配一块内存空间,并返回一个指向这个空间的指针。调用init时对对象进行初始化。如果此时,我们将image这个指针置为nil:image=nil;那样将造成内存泄露,系统分配给image的空间永远无法回收。所以,在我们不需要image这个对象时,我们会使用dealloc方法将其交还给系统:[image dealloc];然而这里,有将产生一个严重的问题,如果我们此时打印image的指针,会发现它现在成了一个危险东西,因为它指向的东西不存在了,而它却依然指向那个地方,这便是很多程序员的噩梦:野指针。为此,我们应该养成一个好习惯,不用的指针置为nil,所有对空指针进行的操作都被认为是安全的。

通过上面的理解,我们发现了一个非常麻烦的地方,我申请了一块内存空间,如果我将指针置空了而没有释放对象,则会内存泄露,如果我提前释放了对象,又很可能会有野指针的出现。并且如果有很多类都引用了这个对象,我甚至的不知道我应该什么时候释放它。因此,Object-C为我们引入了引用计数这种管理内存的方法,任何引用这个对象的地方,都应该让这个对象的引用计数加1。同样,任何不再需要这个对象的地方,也应该使它的引用计数减1,如此一来,对象内存便被统一的管理了起来。

五、内存管理的黄金法则

引用计数内存管理的机制是对象的计数,每个对象至少会有一个引用者,如果没有了引用者,对象会被释放。

黄金法则:

1、当你使用alloc,new,copy,mutableCopy创建对象时,你才需要管理他们。

2、你可以使用retain给一个对象增加引用计数。

3、当你不再需要一个对象时,你必须调用release减少其引用计数。

4、你不能释放不属于你的对象的所有权。

上面就是黄金法则的所有内容,我译的可能不到位,总结为一点,也是至关重要的一点就是:谁创建了对象,谁释放掉对象。谁增加了引用计数,谁就在不用时减少计数。alloc,new,copy,mutableCopy,retain这些方法会使引用计数增加,release会使引用计数减少,当计数为0时,系统会调用dealloc释放内存。

六、自动释放池

为了方便内存管理,避免我们频繁的调用release方法,Object-C中还为我们引用了一种机制:自动释放池。自动释放池的原理其实只是延时释放,它并没有帮我们做太多的工作。自动释放池的使用方式有两种:

1、MRC时:

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];//创建一个自动释放池,系统默认会为我们创建一个,我们也可以创建自己的。
    UIImage * image = [[[UIImage alloc]init] autorelease];//在池内创建一些对象,会和最近的自动释放池匹配
    [pool release];//这时自动释放池会向池子中的每一个对象发送release消息

2、ARC时:

  @autoreleasepool {
        UIImage * image = [[[UIImage alloc]init] autorelease];
    }

疏漏之处 欢迎指正

学习使用 欢迎转载

专注技术,热爱生活,交流技术,也做朋友。 ——珲少 QQ群:203317592

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏后端技术探索

非Java程序员竟鲜有人真正理解DI和IOC

小编在后端圈也算是阅人无数了, 发现一个现象,Java程序员对于面向对象语言的基础知识整体掌握比较扎实,而类似PHP,Python的初级甚至中级程序员就比较薄弱...

2082
来自专栏JavaEdge

设计模式实战 - 简单工厂

最可能给八卦炉下达什么样的生产命令呢? 应该是给我生产出一个黄色人种(YellowHuman类) 而不会是给我生产一个会走、会跑、会说话、皮肤是黄色的人种 ...

1225
来自专栏aCloudDeveloper

大神洗礼第一讲——防御性编程相关

Author:bakari           Date:2012.10.18 这段时间非常有幸能够跟着一个非常牛的学长学习编程,现将每次学到的内容作为整理,方...

19210
来自专栏hrscy

202 - Swift 的核心是什么?

不知道大家有没有看过 WWDC 2015 的视频,其中有一个编号为 408 的视频解释了这个问题,下面是视频链接:Protocol-Oriented Progr...

1392
来自专栏LinkedBear的个人空间

设计模式笔记(一)——设计模式的引入与三大工厂模式

设计模式(Design Pattern)是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总...

702
来自专栏娱乐心理测试

ARC 环境下 dealloc 的使用误区

在MRC时代,我们需要在 dealloc中做很多,比如释放对象,如今我们已经进入ARC时代,对于普通对象的释放,系统已经帮我们做好了;是不是我们就再也不用担心内...

1124
来自专栏林德熙的博客

使用 Resharper 快速做适配器

如果需要做一个类的重写,需要重新写这个类的所有属性和函数,本文提供一个简单的方法让大家快速重写一个类的所有属性和函数。

671
来自专栏walterlv - 吕毅的博客

应该抛出什么异常?不应该抛出什么异常?(.NET/C#)

2018-02-04 13:25

1862
来自专栏哲学驱动设计

EntityFramework 元数据 设计分析

    由于之前已经尝试使用过 EF CodeFirst CTP4,所以这次在EF4.1发布的第三天,在 OEA 框架中已经支持使用它来实现数据访问层。而且,我...

1908
来自专栏NetCore

[原创]Fluent NHibernate之旅(三)-- 继承

经过了“开篇”和“简单映射”两篇文章,相信大家对Fluent NHibernate 有了一定的了解了,FluentNHibernate实际就是对 NHibern...

2028

扫码关注云+社区

领取腾讯云代金券