iOS另类的内存管理

移动开发 iOS
OS的内存管理算是老生常谈的问题了,我们写iOS的时候无时无刻不在涉及到内存管理。从开始的MRR(manual retain-release)到后来ARC(Automatic Reference Counting),包括CoreFoundation的内存管理都遵守引用计数的基本原则。

[[129290]]

OS的内存管理算是老生常谈的问题了,我们写iOS的时候无时无刻不在涉及到内存管理。从开始的MRR(manual retain-release)到后来ARC(Automatic Reference Counting),包括CoreFoundation的内存管理都遵守引用计数的基本原则。

基本的内存管理大家肯定都很熟悉,在这里主要说一点,其余的就不多说了。官方文档有这样的一段话

- You own any object you create

You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).

大意就是说,如果你使用alloc/new/copy/mutableCopy这些开头的方法创建了一个对象,那么你就会拥有这个对象(retain)。当你不用的时候,你就需要手动的去release一次。

举一个例子,假设有一个方法,[STObject newObject]

我们应该这么使用,如果我们***不release,就会导致Object被泄漏。

  1. STObject *object = [STObject newObject]; 
  2. // do something 
  3. [object release]; 

既然这样的话,我们也可以想象出如果我们要自己实现new开头的方法,我们需要如下代码

  1. - (instancetype)newObject { 
  2.     return [[[self class] alloc] init]; 
  3. + (UIButton *)copyButton { 
  4.     return [[UIButton buttonWithType:UIButtonTypeCustom] retain]; 

那么就产生了以下几个问题:

MRR下实现了一个newObject方法,该方法遵守约定的原则,返回值会retain+1,然后在ARC下调用该方法创建对象

MRR下实现了一个newObject方法,该方法没有遵守约定原则,返回autorelease的对象,然后在ARC下调用该方法创建对象

ARC下实现了一个newObject方法,然后在MRR下调用newObject方法创建对象,使用完成之后release

ARC下实现了一个newObject方法,然后在MRR下调用newObject方法创建对象,使用完成之后没有release

我们可以自己编写以上的实验代码,然后测试。

最终测试结果如下:

场景1,3下运行正常

场景2下会crash

场景4下产生内存泄露

为什么场景2会crash呢?这是由于ARC下我们编译器如果看到你是以alloc/new/copy/mutableCopy等开头的方法创建了对象,则会在使用的***插入一次release操作,由于返回的是autorelease的对象,又被release了一次,所以导致野指针。

场景4产生泄漏的原因也是一样,ARC下编译器发现该方法是new等开头的时候,方法结束的时候不会插入release语句,场景4使用的过程中,没有对newObject进行release,所以会产生泄漏。

如果我们仅使用MRR或者ARC的话,这种问题一般不会出现。这种问题的出现一般是当ARC/MRR混编的时候,由于一些编写的不规范导致的,所以在写代码的过程中,遵守规范是很有必要的。

如果我们自己编写alloc/new/copy/mutableCopy开头的方法的时候,MRR下一定不要忘了返回retain的对象,同样当我们使用alloc/new/copy/mutableCopy的方法创建对象的时候,也不能忘了在用完之后release。

如果我们有一段MRR的代码,提供了一个new开头的方法但是没有遵守规范,我们ARC下该怎么办呢?按照上面的结论,我们正常使用肯定会导致野指针的

在这里呢,如果能改代码当然把代码都改成遵守规范的***,如果不能改源码的话,我们只能修改使用方。在这里提供一种方法:

  1. SEL selector = NSSelectorFromString(@"copyObject"); 
  2. STObject *object = (STObject *)[STObject performSelector:selector]; 

大家可以尝试一下,然后思考一下为什么。

关于iOS的内存管理远远不止这些,本文中说的大家实际编码的过程中也很少遇到,仅仅当作知识的补充吧~   

责任编辑:chenqingxiang 来源: 技术哥的博客
相关推荐

2018-07-23 09:26:08

iOS内存优化

2017-02-09 21:24:22

iOS内存管理

2017-03-07 10:15:35

iOS内存管理开发

2011-07-21 14:42:45

iOS UIViewCont 内存

2016-04-11 09:30:49

内存管理ios开发

2015-06-25 09:47:20

iOS内存管理

2014-03-12 09:37:22

内存管理autoreleaseautorelease

2011-12-29 09:24:54

iOS应用下载排行榜

2011-08-05 16:41:48

iOS 队列 内存

2016-03-03 10:07:39

ios内存管理面试总结

2011-07-21 17:40:43

iOS 多核 内存

2011-08-22 11:07:16

IOS 开发多核内存

2020-03-10 18:53:16

移动支付另类支付APP

2010-11-23 11:16:35

MySQL表别名

2009-10-23 17:10:27

试用达人

2011-09-01 10:42:14

Objective-CCocoa内存管理

2011-04-25 13:13:02

Javafinalize

2015-09-25 10:58:20

2013-07-19 13:16:26

iOS中BlockiOS开发学习内存管理

2012-06-15 17:50:26

点赞
收藏

51CTO技术栈公众号