ARC(二) ARC规则
2016-07-18 21:00
573 查看
1. 不能使用retain/release/retainCount/autorelease
ARC有效时,内存管理就成了编译器的工作,所以就没有必要使用内存管理的方法(retain/release/retainCount/autorelease)。如果使用了这些代码,就会发生编译错误。
2.必须遵守内存管理的方法命名规则
在ARC无效时,用于对象生成/持有的方法必须遵守以下的命名规则:
alloc
new
copy
mutableCopy
以上述名称开始的方法在返回对象时,必须返回给调用方所应当持有的对象。在ARC有效时,以上规则同样要遵守,但是还要再加上一个:
init
以init开始的方法,比上面的规则更加严格。该方法必须是实例方法,而且必须返回对象。返回的对象,应为id类型或者该方法声明类的类型,也可以是该类的父类或者子类的类型。
init主要和alloc方法配合使用。
3.不能显式调用dealloc
在ARC有效时,不能显式调用dealloc,不然会引起编译错误。
4.使用@autoreleasepool块代替NSAutoreleasePool
在ARC有效时,不能使用NSAutoreleasePool,不然会引起编译错误。如果想要使用autorelease,只能使用@autoreleasepool块。
5. 不能使用区域(NSZone)
NSZone 是为了防止内存碎片而导入的一项措施。系统根据对象的使用目的、尺寸,分配其所属的Zone区域,以提高对象的访问效率,避免不必要的内存碎片。但是,现在的运行时系统(用编译开关
6.对象类型变量不能作为C语言结构体的成员
在C语言的结构体(struct或者union)成员中,如果存在Objective-C对象型变量,便会引起编译错误。
原因是:ARC把内存管理的工作分配给了编译器,所以编译器必须要知道并管理对象的生存周期,但是C语言没有办法来管理结构体成员的生存周期。
如果一定要将Objective-C对象型变量加入到结构体成员中,可以将它强制转换成void*,或者是附加_unsafe_unretained修饰符。
7.显示转换id和void*
在ARC无效时,可以直接进行强制转换,比如:
但是在ARC有效时,这样会产生编译错误。这时,可以使用_bridge、_bridge_retained或者_bridge_transfer来进行转换。
(1)_bridge
如果只是想单纯地赋值,可以使用_bridge来进行转换,例如:
但是,这样做的安全性很低,很容易产生悬垂指针,从而导致程序崩溃。
(2)_bridge_retained
_bridge_retained可以使要转换赋值的对象也持有所赋值的对象,类似于ARC无效情况下的retain,例如:
上面的源码,等同于以下源码:
(3)_bridge_transfer
_bridge_transfer提供和_bridge_retained相反的动作,转换结束后,转换目标持有该对象,而被转换的变量不再持有该对象,类似于RC无效情况下的release,例如:
上面的源码,等同于以下源码:
ARC有效时,内存管理就成了编译器的工作,所以就没有必要使用内存管理的方法(retain/release/retainCount/autorelease)。如果使用了这些代码,就会发生编译错误。
2.必须遵守内存管理的方法命名规则
在ARC无效时,用于对象生成/持有的方法必须遵守以下的命名规则:
alloc
new
copy
mutableCopy
以上述名称开始的方法在返回对象时,必须返回给调用方所应当持有的对象。在ARC有效时,以上规则同样要遵守,但是还要再加上一个:
init
以init开始的方法,比上面的规则更加严格。该方法必须是实例方法,而且必须返回对象。返回的对象,应为id类型或者该方法声明类的类型,也可以是该类的父类或者子类的类型。
init主要和alloc方法配合使用。
3.不能显式调用dealloc
在ARC有效时,不能显式调用dealloc,不然会引起编译错误。
4.使用@autoreleasepool块代替NSAutoreleasePool
在ARC有效时,不能使用NSAutoreleasePool,不然会引起编译错误。如果想要使用autorelease,只能使用@autoreleasepool块。
5. 不能使用区域(NSZone)
NSZone 是为了防止内存碎片而导入的一项措施。系统根据对象的使用目的、尺寸,分配其所属的Zone区域,以提高对象的访问效率,避免不必要的内存碎片。但是,现在的运行时系统(用编译开关
_OBJC2_ 指定的情况下)是不支持Zone概念的。所以,不管ARC是否有效,都不能使用 NSZone。
6.对象类型变量不能作为C语言结构体的成员
在C语言的结构体(struct或者union)成员中,如果存在Objective-C对象型变量,便会引起编译错误。
Struct A{ NSMutableArray *array; }
原因是:ARC把内存管理的工作分配给了编译器,所以编译器必须要知道并管理对象的生存周期,但是C语言没有办法来管理结构体成员的生存周期。
如果一定要将Objective-C对象型变量加入到结构体成员中,可以将它强制转换成void*,或者是附加_unsafe_unretained修饰符。
Struct A{ NSMutableArray _unsafe_unretained *array; }
7.显示转换id和void*
在ARC无效时,可以直接进行强制转换,比如:
id obj = [[NSObject alloc] init]; void * p = obj;
但是在ARC有效时,这样会产生编译错误。这时,可以使用_bridge、_bridge_retained或者_bridge_transfer来进行转换。
(1)_bridge
如果只是想单纯地赋值,可以使用_bridge来进行转换,例如:
id obj = [[NSObject alloc] init]; void * p = (_bridge void*)obj; id o = (_bridge id)p;
但是,这样做的安全性很低,很容易产生悬垂指针,从而导致程序崩溃。
(2)_bridge_retained
_bridge_retained可以使要转换赋值的对象也持有所赋值的对象,类似于ARC无效情况下的retain,例如:
id obj = [[NSObject alloc] init]; void * p = (_bridge_retained void*)obj;//此时,变量p和obj都持有该对象
上面的源码,等同于以下源码:
/*ARC无效*/ id obj = [[NSObject alloc] init]; void *p = obj; [(id)p retain];
(3)_bridge_transfer
_bridge_transfer提供和_bridge_retained相反的动作,转换结束后,转换目标持有该对象,而被转换的变量不再持有该对象,类似于RC无效情况下的release,例如:
id obj = (_bridge_transfer id)p;//此时,id持有该对象,而p不再持有该对象
上面的源码,等同于以下源码:
/*ARC无效*/ id obj = (id)p; [obj retain]; [(id)p retain];
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 页面缓存:内存和文件之间的那些事
- Lua的内存管理浅析
- 跟我学习JScript的Bug与内存管理
- 跟我学习javascript的垃圾回收机制与内存管理
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- js判断客户端是iOS还是Android等移动终端的方法
- iOS应用开发中AFNetworking库的常用HTTP操作方法小结
- iOS应用中UISearchDisplayController搜索效果的用法
- iOS App开发中的UISegmentedControl分段组件用法总结
- IOS开发环境windows化攻略
- iOS应用中UITableView左滑自定义选项及批量删除的实现
- iOS中UIAlertView警告框组件的使用教程