服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - 详解iOS应用开发中的ARC内存管理方式

详解iOS应用开发中的ARC内存管理方式

2021-01-07 15:23M了个J IOS

这篇文章主要介绍了详解iOS应用开发中的ARC内存管理方式,文中示例基于Objective-C语言,需要的朋友可以参考下

提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量"

零、简介
arc是自ios 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切
注意:arc 是编译器特性,而不是 ios 运行时特性(除了weak指针系统),它也不是类似于其它语言中的垃圾收集器。因此 arc 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化

一、arc的开启和禁止
要想将非arc的代码转换为arc的代码,大概有2种方式:
(1).使用xcode的自动转换工具
(2).手动设置某些文件支持arc

1、xcode的自动转换工具
xcode带了一个自动转换工具,可以将旧的源代码转成arc模式
(1).arc是llvm 3.0编译器的特性,而现有工程可能使用老的gcc 4.2或llvm-gcc编译器,因此首先需要设置使用llvm 3.0编译器:
(现使用的xcode4.5,llvm 3.0已经升级到llvm 4.1)

详解iOS应用开发中的ARC内存管理方式

最好也选上warnings中的other warning flags 为 -wall,这样编译器就会检查所有可能的警告,有助于我们避免潜在的问题

(2).build options下面的run static analyzer选项也最好启用,这样每次xcode编译项目时,都会运行静态代码分析工具来检查我们的代码

详解iOS应用开发中的ARC内存管理方式

(3).设置"objective-c automatic reference counting"选项为yes,不过xcode自动转换工具会自动设置这个选项,这里只是说明一下如何手动设置

详解iOS应用开发中的ARC内存管理方式

(4).打开xcode的自动转换工具

详解iOS应用开发中的ARC内存管理方式

(5).xcode会显示一个新窗口,让你选择哪些文件需要转换

详解iOS应用开发中的ARC内存管理方式

点击check按钮,xcode可能会弹出对话框提示项目不能转换为arc,需要你准备好转换(这里暂时省略详细说明)
(6).如果没有什么警告、错误了,就会弹出一下提示窗口:

详解iOS应用开发中的ARC内存管理方式

(7).点击next,几秒钟后,xcode会提示所有文件的转换预览,显示源文件的所有改变。左边是修改后的文件,右边是原始文件。在这里你可以一个文件一个文件地查看xcode的修改,以确保xcode没有改错你的源文件:

详解iOS应用开发中的ARC内存管理方式

点击save即可完成转换
(8).自动转换之后,xcode会移除所有retain、release、autorelease调用,这可能会导致代码出现其它警告、无效语法等,这些都需要自己手工进行修改
注意:xcode的自动转换工具最好只使用一次,多次使用可能会出现比较诡异的问题。假如你第一次转换没有转换所有的文件,当你稍后试图再次转换剩余的文件时,xcode实际上不会执行任何转换操作。因此最好一次就完成转换,没有转换的文件可以考虑手工进行修改
2、手动开启某些文件的arc
在compiler flags一列加上-fobjc-arc就表示开启这个.m文件的arc

详解iOS应用开发中的ARC内存管理方式

3、禁止某些文件的arc

详解iOS应用开发中的ARC内存管理方式

在compiler flags一列加上-fno-objc-arc就表示禁止这个.m文件的arc


二、原理
arc 的规则非常简单:只要还有一个变量指向对象,对象就会保持在内存中。当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的

三、strong指针
控制器中有个文本输入框框属性

复制代码 代码如下:

 

@property (nonatomic, assign) iboutlet uitextfield *namefield; 

 


1.如果用户在文本框中输入mj这个字符串

 

详解iOS应用开发中的ARC内存管理方式

那么就可以说,namefield的text属性是nsstring对象的指针,也就是拥有者,该对象保存了文本输入框的内容

详解iOS应用开发中的ARC内存管理方式

2.如果执行了如下代码

复制代码 代码如下:

 

nsstring *name = self.namefield.text; 

 


一个对象可以有多个拥有者,在上面代码中,name变量同样也是这个nsstring对象的拥有者,也就是有两个指针指向同一个对象

 

详解iOS应用开发中的ARC内存管理方式

3.随后用户改变了输入框的内容,比如

详解iOS应用开发中的ARC内存管理方式

此时namefeild的text属性就指向了新的nsstring对象。但原来的nsstring对象仍然还有一个所有者(name变量),因此会继续保留在内存中

详解iOS应用开发中的ARC内存管理方式

4.当name变量获得新值,或者不再存在时(如局部变量方法返回时、实例变量对象释放时),原先的nsstring对象就不再拥有任何所有者,retain计数降为0,这时对象会被释放
如,给name变量赋予一个新值

 

复制代码 代码如下:


name = @"jake"; 

 

 

 

 

详解iOS应用开发中的ARC内存管理方式

我们称name和namefield.text指针为"strong指针",因为它们能够保持对象的生命。默认所有实例变量和局部变量都是strong指针

四、weak指针
weak型的指针变量仍然可以指向一个对象,但不属于对象的拥有者
1.执行下面的代码

复制代码 代码如下:

__weak nsstring *name = self.namefield.text;

 

 

详解iOS应用开发中的ARC内存管理方式

name变量和namefield.text属性都指向同一个nsstring对象,但name不是拥有者

2.如果文本框的内容发生变化,则原先的nsstring对象就没有拥有者,会被释放,此时name变量会自动变成nil,称为空指针

详解iOS应用开发中的ARC内存管理方式

weak型的指针变量自动变为nil是非常方便的,这样阻止了weak指针继续指向已释放对象,避免了野指针的产生,不然会导致非常难于寻找的bug,空指针消除了类似的问题

3.weak指针主要用于“父-子”关系,父亲拥有一个儿子的strong指针,因此父亲是儿子的所有者;但为了阻止所有权循环,儿子需要使用weak指针指向父亲。典型例子是delegate模式,你的viewcontroller通过strong指针(self.view)拥有一个uitableview, uitableview的datasource和delegate都是weak指针,指向你的viewcontroller

详解iOS应用开发中的ARC内存管理方式

五、strong和weak指针的使用注意
1.下面代码是有问题的:

复制代码 代码如下:

__weak nsstring *str = [[nsstring alloc] initwithformat:@"1234"]; 
nslog(@"%@", str); // 打印出来是"(null)" 


str是个weak指针,所以nsstring对象没有拥有者,在创建之后就会被立即释放。xcode还会给出警告("warning: assigning retained object to weak variable; object will be released after assignment")
2.一般的指针变量默认就是strong类型的,因此一般我们对于strong变量不加__strong修饰,以下两行代码是等价的:

复制代码 代码如下:

nsstring *name = self.namefield.text; 
__strong nsstring *name = self.namefield.text; 


3.属性可以是strong或weak,写法如下

复制代码 代码如下:

@property (nonatomic, strong) nsstring *name; 
@property (nonatomic, weak) id delegate; 


4.以下代码在arc之前是可能会行不通的,因为在手动内存管理中,从nsarray中移除一个对象时,这个对象会发送一条release消息,可能会被立即释放。随后nslog()打印该对象就会导致应用崩溃

复制代码 代码如下:

id obj = [array objectatindex:0]; 
[array removeobjectatindex:0]; 
nslog(@"%@", obj); 


在arc中这段代码是完全合法的,因为obj变量是一个strong指针,它成为了对象的拥有者,从nsarray中移除该对象也不会导致对象被释放

 

六、arc小结
1.有了arc,我们的代码可以清晰很多,你不再需要考虑什么时候retain或release对象。唯一需要考虑的是对象之间的关联,也就是哪个对象拥有哪个对象?
2.arc也有一些限制:
1> 首先arc只能工作于objective-c对象,如果应用使用了core foundation或malloc()/free(),此时还是需要你来手动管理内存
2> 此外arc还有其它一些更为严格的语言规则,以确保arc能够正常地工作
3.虽然arc管理了retain和release,但并不表示你完全不需要关心内存管理的问题。因为strong指针会保持对象的生命,某些情况下你仍然需要手动设置这些指针为nil,否则可能导致应用内存不足。无论何时你创建一个新对象时,都需要考虑谁拥有该对象,以及这个对象需要存活多久
4.arc还能很好地结合c++使用,这对游戏开发是非常有帮助的。对于ios 4,arc有一点点限制(不支持weak指针),但也没太大关系

七、arc使用注意总结
1.不能直接调用dealloc方法,不能调用retain,release,autorelease,retaincount方法,包括@selector(retain)的方式也不行
2.可以用dealloc方法来管理一些资源,但不能用来释放实例变量,也不能在dealloc方法里面去掉[super dealloc]方法,在arc下父类的dealloc同样由编译器来自动完成
3.core foundation类型的对象仍然可以用cfretain,cfrelease这些方法
4.不能再使用nsallocateobject和nsdeallocateobject对象
5.不能在c结构体中使用对象指针,如果有类似功能可以创建一个objective-c类来管理这些对象
6.在id和void*之间没有简便的转换方法,同样在objective-c和core foundation类型之间的转换都需要使用编译器制定的转换函数
7.不能再使用nsautoreleasepool对象,arc提供了@autoreleasepool块来代替它,这样更有效率
8.不能使用内存存储区(不能再使用nszone)
9.不能以new为开头给一个属性命名
10.声明iboutlet时一般应当使用weak,除了对storyboard这样nib中间的顶层对象要用strong
11.weak相当于老版本的assign,strong相当于retain

延伸 · 阅读

精彩推荐
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22