ARC 与非 ARC 之间那些的'祸害'
你是否也曾被 assign、retain、copy、release、autorelease、strong、__strong、weak、__weak、__unsafe__unretain、__autoreleasing、__bridge、__bridge__transfer、__bridge__retained这些个 ARC 和非 ARC 之间的『祸害』搞的晕头转向,四肢无力,整个人都不好了。
好吧,是时候来个了断了。
一.认识到以下事实
- ARC 是 LLVM 3.0 编译器的一个新特性,它是编译时特性而不是运行时特性,它所做的事情其实就是编译程序的时候在以前需要手动管理内存的地方自动的为你添加retain 和 release。
- ARC 的性能优于手动内存管理。但是它只适用于 Objective-C 对象,而 iOS 中基于 C 语言的 API 会用到 Core Foundation对象(CFxxxx),对于这些 CF 对象,依然需要手动内存管理。
- ARC 是 Objective-C 的必然趋势,务必顺势而为。
二.assign、retain、copy、release、autorelease
- assign,直接赋值,适用于 Int、BOOL、Float 等基本数据类型。如果是用在 Objective-C对象(指针)身上,如 NSString *a=b,则表示a 同时指向 b 指向的那一块内存,但是引用计数不变。这样会导致如下问题:当 b 指向的内存被释放时,a 并不知情,a就成了野指针,程序崩溃。
- retain,用在Objective-C对象(指针)身上,赋值时指向同一块内存,引用计数加一。很明显,retain 不用于 Int、BOOL 等基本数据类型,也不能用于 CF 对象,原因在于这些根本就没有引用计数。
- copy,与 retain 的区别在于赋值时会重新开辟一块新的内存并复制。
- release,引用计数减一,当引用计数为0时就会释放掉对应的内存。
- autorelease,在 autorelease pool 中自动 release 对象。
三.Strong、weak、__Strong、__weak、__unsafe__unretained、__autoreleasing
- Strong,iOS5.0以及 Mac OS X10.7之后引入的新特性,也即是在新的 SDK 中用 Strong 和 weak 来表示强引用和弱引用。Strong 相当于前面的 retain。Strong 的含义是只要还有指针指向它,那么这个对象就一直活着,内存不会被释放。Strong 用于声明属性(property),而__Strong用于声明实例变量和局部变量,默认情况下实例变量和局部变量都是 strong 型的,所以你不需要再声明一遍。
- Weak,对应于之前的 assign,弱引用,如果指向的对象被释放,那么指针被置为 nil。__weak用于实例变量和局部变量。
- 在使用 strong 时,可能会导致retain cycle。例如,你拥有一个对象包含了另外了一个实例变量对象,但是第二个对象又把前一个对象作为它的委托,那么这两个对象将不会被释放。所以需要把 delegate 设为 weak。
- __unsafe__unretained,类似于__weak,差别在于,当所指向的对象被释放时,__unsafe__unretained 修饰的指针不会被置为nil 而会成为野指针,正如它的名字 unsafe 所暗示的。这是应该极力避免的。但为什么还要用__unsafe__unretained 呢,因为__weak 是 iOS5以后才出现的。
- __autoreleasing 的英文解释为:to denote arguments that are passed by reference (id *) and are autoreleased on return,即主要是在引用传参时使用。
四.__bridge、__bridge__transfer、__bridge__retained
- 在 Objective-C 对象和 CF 对象之间转换的时候需要用到 bridge cast.
- 当你要临时的使用一个类型,而不想要更改所有关系时, 你要使用 __bridge。转换值 = 原变量指针; (原变量如果释放, 转换值也就不能使用了)
- 当把所有关系从 Core Foundation 转换到 Objective-C 的时候, 你要使用 CFBridgingRelease(),也就是__bridge__transfer。把内存管理的权利从 CF 转交给 ARC。所有你调用名称含有 Create,Copy 或 Retain 的 Core Foundation 函数的地方, 你都必须使用 CFBridgingRelease() 来将返回值转移到 ARC 中。
- 当把所有关系从 Objective-C 转换到 Core Foundation 的时候,你要使用 CFBridgingRetain(),也就是__bridge__retained。把内存管理的权利从 ARC 转为 CF,这时需要手动内存管理也即是在使用完 CF 对象之后调用 CFRelease()。
- Notes:
- 不是所有的 Objective-C 和 Core Foundation对象都是可以直接转换(toll-free bridged)的。例如, CGImage 和 UIImage 就不能互相转换, CGcolor 和 UIColor 也不能。这里列出了所有能够相互转换的类型。
- __bridge 转换,不仅限于 Core Foundation,也用于 一些API 使用 的void * 类型的指针, 可以让你存放任何类型的引用。
原文地址:http://blog.csdn.net/zhuiyi316/article/details/23794471
总结很不错,怕作者删了,拷过来以记之
ARC 与非 ARC 之间那些的'祸害'的更多相关文章
- ARC 与非ARC 之间的转换,以及如何使一个项目中,ARC与非ARC共存
1,非ARC 转 ARC的操作 XCode 的 Edit -- Refactor -- Convert to Object-C ARC (注意,一般在一个大项目中,很少直接使用此方法,其正确率有待考虑 ...
- 1.ARC和非ARC文件共存
1.ARC和非ARC文件共存 项目->Build Parses->对应的类 1.1.新项目兼容老的非ARC:-fno-objc-arc 1.2.老项目兼容ARC:-fobjc-arc
- ios工程中ARC与非ARC的混合
ARC与非ARC在一个项目中同时使用, 1,选择项目中的Targets,选中你所要操作的Target,2,选Build Phases,在其中Complie Sources中选择需要ARC的文件双击,并 ...
- iOS: ARC和非ARC下使用Block属性的问题
1. Block的声明和线程安全 Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非AR ...
- ARC简介以及工程中ARC与非ARC的混合
Piosa 博客园 博问 闪存 首页 新随笔 联系 管理 订阅 随笔- 79 文章- 0 评论- 13 ARC简介以及工程中ARC与非ARC的混合 ARC与非ARC在一个项目中同时使用, ...
- (转)iOS 开发,工程中混合使用 ARC 和非ARC
[前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...
- IOS ARC和非ARC文件混用
ARC在SDK4.0的时候增加的,因为要和曾经的项目融合,就会有arc和非arc文件的混合. 当然,也就这两种情况: 1.自己的旧项目没有使用ARC,可是引入的第三方库却是使用了ARC的. 2.自己的 ...
- iOS 开发,工程中混合使用 ARC 和非ARC(转)
[前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...
- ARC简介以及工程中ARC与非ARC的混合(转)
ARC与非ARC在一个项目中同时使用, 1,选择项目中的Targets,选中你所要操作的Target,2,选Build Phases,在其中Complie Sources中选择需要ARC的文件双击,并 ...
随机推荐
- MongoDB 安装
年初换了个硬盘空间更大的vps,这下终于可以装MongoDB了. 1 配置包管理系统(yum) 建立 /etc/yum.repos.d/mongodb-org-3.2.repo文件.内容如下: [mo ...
- 在SQL SERVER中实现RSA加解密函数(第二版)
/*************************************************** 作者:herowang(让你望见影子的墙) 日期:2010.1.5 注: 转载请保留此信息 更 ...
- [原创]Mac系统下制作OS 10.11安装镜像
一.所需软件 1.从App Store下载OS X El Capitan 10.11.2 ------------------------------------------------------- ...
- 关于DOM的一些操作 整理 积累
var chils= s.childNodes; //得到s的全部子节点 var par=s.parentNode; //得到s的父节点 var ns=s.nextSbiling; //获得 ...
- 读取EXCEL数据到内存DataTable
protected void Page_Load(object sender, EventArgs e) { string filepath = Server.MapPath("~/file ...
- border
1.border-width:不支持百分比值 支持下面属性值: thin:1px medium:3px thick:5px 2.border-style类型 solid:实线 dashed:虚线(方形 ...
- 从零开始山寨Caffe·壹:仰望星空与脚踏实地
请以“仰望星空与脚踏实地”作为题目,写一篇不少于800字的文章.除诗歌外,文体不限. ——2010·北京卷 仰望星空 规范性 Caffe诞生于12年末,如果偏要形容一下这个框架,可以用"须敬 ...
- 初识SQL 执行顺序
SQL不同于一般的程序代码,会按照一定的顺序进行执行,他的第一个执行始终从from开始执行,虽然Select出现在第一位置但是执行顺序 确不是在第一个.有时候可能大家写了很久的代码,不一定能够很好的理 ...
- RCurl getURL()函数做debug
getURL()函数做获取网页做debug,三步骤 1.首先创建一个对象debugGatherer(),该对象包含三个函数:(update(), value(), reset()); R> de ...
- 用Struts2拦截器实现文件下载前的验证
思想:用户登录后,将登录信息存储在session中,每次需要验证时,取出来验证 缺陷:没有实现多用户登录时的情况 实行步骤: 登录信息的存储: ActionContext actionContext ...