ARC 概要
来源:互联网 发布:mac page up 编辑:程序博客网 时间:2024/06/05 04:16
三年前,Xcode开发就一直推崇使用ARC内存管理机制,再往前的岁月里使用的是MRC,那时候retain和release随处可见,显然MRC已经成为历史,着眼当下:
这里简要罗列了 ARC 的一些知识点概要,
这是一个学习并存在容错的文档翻译。
Transitioning to ARC Release Notes
1. 首先介绍一个概念:
现在的 OS X系统和 iOS系统都是没有 垃圾回收的(GC Garbage Collection)苹果使用的内存管理的方法是:应用计数 机制。从原有的MRC过度到现在更加先进的ARC 机制。
2. ARC 使用中感受到最大的好处(如果曾有MRC体验 will more feel):
对于果农来说,再也不用费尽心思考虑对象的retain和 release 操作了,解放出庞大的能量,使得更能够专注在有趣的code环节
3. 概要一下ARC:
3.1 ARC和MRC都是对遵循着相同的内存管理法则,然而ARC更加优秀,它会在编译的时候(compile time)自动添加一些code来确保对象的必要和生命力。对于其可靠性,(maybequestion apple)
3.2 为了确保编译器自动生成正确代码,ARC对toll-free bridging(Coare Fundation <-> OC Object)方法做了限制约束;ARC添加了一些新的对象引用的生命周期修饰符, 和一些属性声明。
3.3 ARC 起用于系统版本: Xcode4.2, OS X v10.7 ,iOS 5,
3.4 Xcode 更改工程到ARC模式方法:(choose Edit > Convert to Objective-C ARC);另外对于当个文件,可以使用编译标识来启动或者取消ARC(Target > Build Phases > Compile Sources):弃用ARC使用 -fobjc-arc ;禁用ARC 使用 -fno-objc-arc标识对应文件即可。
4. ARC中一些硬性规则:
这些规则都是为了让内存管理模式更加可靠,这些规则只在ARC编译模式下发生作用,既然是硬性的,如果违背就会即刻生成编译时报错。
4.1 不能实现或调用:retain,release,retainCount或者autorelease。拓展为不能用@selector(retain),@selector(relase)等。
也不能直接调用dealloc函数,dealloc函数在ARC机制下不需要(也不能、会导致编译错误)调用【super dealloc】,它其实是在编译时候自动添加到代码中。对于CoreFoundation-syle objects,任然可以使用CFRetain,CFRelease。
4.2 不能使用 NSAllocateObject或者 NSDeallocateObject。使用alloc 穿件对象,运行时会处理好对象的释放。
4.3 不能在C的结构体重使用对象指针,与其使用结构体,可以使用OC对象来管理数据。
4.4 id 和 void * 之间存在差异,id 其实是一个对象结构体指针,在Objective-C对象和Core Foundation类型之间需要做一些特别定位处理
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
4.5 不能使用NSAutoreleasePool对象,ARC提供了@autoreleasepool 块替代,比前者优秀很多。
4.6 无需再使用 NSZone ,OC的运行时机制会忽略它们
4.7 ARC 引入了一些对方法名和属性命名的约束。不能用 new开头的给一个属性的访问器命名,除非设置了一个特意指定的getter:
// Won't work:
@property NSString *newTitle;
// Works:
@property (getter=theNewTitle) NSString *newTitle;
5. ARC 引入的生命时修饰符(Lifetime Qualifiers)
5.1 属性修饰(Property Attributes)
关键字 weak 和 strong。
下面的声明方法同义于: @property(retain) MyClass *myObject;//MRC
@property(strong) MyClass *myObject;//ARC
下面的声明方法相似于: @property(assign) MyClass *myObject;//MRC
@property(weak) MyClass *myObject
在ARC下, stong是默认的对象属性类型。
5.2 变量修饰(Variable Qualifiers)
__strong 默认修饰,只要有一个强引用存在,对象就始终是‘alive’的。
__weak 特别标注不用保留引用对象的alive,当改对象不再存在强引用的时候,弱引用会将至置为nil。
__unsafe_unretained,不保留引用对象的alive,对象武强引用是也不置为nil,如果对象释放,指针将悬垂。
__autoreleasing,
使用方式(ClassName * qualifier variableName)如:
MyClass * __weak myWeakReference;
MyClass * __unsafe_unretained myUnsafeReference;
注意当 __weak 变量实在stack 上的时候:
NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
NSLog(@"string: %@", string);
clang会给出警告:(Assigning retained object to weak variable;object will be released after assignment)
打印结果是:string: (null) ???不得解??
5.3 使用修饰符,避免强引用循环(Strong Reference Cycles)
Quote by Linus Torvalds:"Talk is cheap Show me the code":
As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:
MyViewController * __block myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil;
};
-----------------
Alternatively, you can use a temporary __weak variable. The following example illustrates a simple implementation:
MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyViewController = myController;
myController.completionHandler = ^(NSInteger result) {
[weakMyViewController dismissViewControllerAnimated:YES completion:nil];
};
--------------
For non-trivial cycles, however, you should use:
MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyController = myController;
myController.completionHandler = ^(NSInteger result) {
MyViewController *strongMyController = weakMyController;
if (strongMyController) {
// ...
[strongMyController dismissViewControllerAnimated:YES completion:nil];
// ...
}
else {
// Probably nothing...
}
};
6. ARC 使用心得语法去管理 AutoRelease Pools:
不能直接使用 类:NSAutoreleasePool,可以使用 @autoreleasepool块语法,它更加强大。 如下
@autoreleasepool {
// Code, such as a loop that creates a large number of temporary objects.
}
这个简单的结构可以让编译器合理处理引用计数的状态。进入时,自动释放吃就被嵌入(pushed),当正常退出的时候(break,return,goto,fall-through,and so on )自动释放池就被弹出,不过如果是意外退出的情况,释放池不会弹出(popped)。
7. outlets 应该使用weak,但是nib文件中一些来至文件的持有者的高层级的对象需要使用strong(window,menu bars,custom controller objects, a storyboardscene)
8. Stack 变量将被初始化为nil。
- (void)myMethod {
NSString *name;
NSLog(@"name: %@", name);
}
9. 管理 Toll-Free Bridging
编译器不会自动管理Core Foundation对象的内存。需要直接更具框架的内存管理规则 调用CFRetain和 CFRelease。
如果需要在OC 和CF之间做处理 利用宏定义(objc/runtime.h)或者CF类型的宏(定义在NSObject.h)中。
__bridge CF 和 OC 之间指针转换 武转换持有关系。
__bridge_retained / CFBridgingRetain 将一个OC指针 切换大奥CF指针,并且转移持有关系,需要自己负责释放持有对象关系(使用CFRelease)
__bridge_transfer / CFBridgingRelease 将非OC指针切换为OC型,并且将持有关系交给ARC。
10.dealloc 函数
因为ARC 不会自动 malloc/free,不管理CF对象、文件描述符等的生命周期,所以需要自己写一个dealloc函数来释放这些资源。
完全不用去对一个实例变量进行release,但是需要自己处理一些不遵循ARC的代码,如可能需要插入[self setDelegate:nil]到系统类中。
在ARC中是不允许对dealloc函数调用[super dealloc]的,应为在运行时会自动调用这块代码。
参考文档:ARC Release Notes
- ARC 概要
- ARC内存管理模式概要
- ARC内存管理概要
- 概要
- 概要
- 概要
- 概要
- iOS开发ARC内存管理与Block概要,你都懂了吗?
- iOS开发ARC内存管理与Block概要,你都懂了吗?
- ARC
- ARC
- arc
- ARC
- ARC
- ARC
- ARC
- arc
- ARC
- Java中 Comparator接口 与Comparable 的区别
- leetcode-Reorder List-143
- fwrite与fprintf区别、printf与fprintf区别
- C#项目中WebBrowser控件的应用
- fopen与fread函数分析
- ARC 概要
- 深入探索c++虚函数继承模型
- 第15周阅读程序(2)
- leetcode 83. Remove Duplicates from Sorted List
- 模板方法模式
- JAVA--018集合框架
- 【Hadoop】MapReduce温度排序之二次排序
- spring MVC +Spring + Hibernate + PostgreSQL框架的集成和多租户( 二)
- 内存分区