ARC 学习

来源:互联网 发布:mssql注入写webshell 编辑:程序博客网 时间:2024/06/07 01:49

ARC 学习

 

iOS引入了Automatic Reference Count(ARC),编译器可以在编译时对obj-c对象进行内存管理。

之前,obj-c的内存管理方式称作引用计数,就是obj-c对象每被”使用”一次,引用计数+1,当引用计数为0时,系统会回收内存.用程序语言表达,就是allco的要release,retain/copy的要release.还有某些容器add的,也要release等等.

现如今,ARC使你勿需理会这些内存管理规则,但同时一些语法也相应的作了改变,具体有哪些变化我们一一解析.

首先新建一个工程(注意Xcode得是4.2),选择使用ARC(如果在新建工程的时候没有选择ARC,随后在些代码的时候又想使用ARC,只需在Build Setting中更改),

然后直奔main函数,

int main(int argc, char *argv[]){    @autoreleasepool {        return UIApplicationMain(argc, argv, nil, NSStringFromClass([ZJAppDelegate class]));    }} 

对比未使用ARC的main函数:

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    int retVal = UIApplicationMain(argc, argv, nil, nil);    [pool release];    return retVal;

NSAutoreleasePool在ARC中被禁止使用,替换成@autoreleasepool 函数体.使用@ autoreleasepool,在函数入口的时候,autorelease pool入栈,正常退出时,autorelease pool出栈,从而释放变量. 注意@ autoreleasepool在非ARC模式下,也能使用,并据称使用@autoreleasepool比使用NSAutoreleasePool速度能快6倍, 明显提升程序性能.

然后打开delegate函数,会发现声明的property有个新的关键字:

@property (strong, nonatomic) UIWindow *window;

strong是新的property限定词,相当于之前的retain,还有一个新的限定词是weak相当于assign. 要注意使用weak reference的时候,当你需要使用对象的时候,可能对象已经不存在了.weak的作用通常只在于避免循环引用.

再查看任一m文件,你会发现没有dealloc函数.ARC中dealloc不需要显示实现,编译器会自己实现.有时候你设计的类会有delegate对象,这时你可以实现dealloc函数在其中将delegate置为nil,但是不要调用[super dealloc],编译器自己会调用.

此外,ARC还有变量限定词:__strong,__weak,__unsafe_unretained和__autoreleasing

__strong是默认的,__weak表明对象是zeroing weak reference,意思是当对象所指向的内存销毁了,zidong置为空nil. __unsafe_unretained是对对象的非zeroing的weak reference,意思是当对象所指向的内存被销毁了,对象还存在,成为”野指针”.__ autoreleasing用于对(id *)类型的参数传递.

Apple举了个例子,

NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];NSLog(@"string: %@", string);

因为在初始化的时候声明了__weak,即zeroing weak reference,初始化完后立马会被销毁,所以NSLOg时显示NULL.

因为ARC是编译时进行的,我们还可以选择哪些文件使用ARC编译,如图:

对于要自己管理内存的文件,设置值为-fno-objc-arc即可。

最后,简单的总结下ARC下新规则:

  • 不能使用retai,release,retainCount,autorelease,NSAutoreleasePool. 通常情况下dealloc函数不需要实现,除非你需要置delegate为nil.
  • Strong相当于retain,weak相当于assign.
  • 声明的property中,不能以new开头.

有不正确的地方,欢迎大家批评指正。


====================================================================================

ARC的工作原理是,在你编译程序时,将内存操作的代码(retain,release或autorelease)自动添加到需要的位置。即底层上使用和Manual Reference Counting(手工引用计数)一样的内存管理机制,但由于XCode自动帮你在编译时添加内存操作的代码,从而简化了编程的工作。

启用ARC,编译选项中需加上-fobjc-arc,不过这个由XCode在创建工程模板时帮你完成。

XCode 4.2以前版本都不支持ARC。

对操作系统也有要求:Mac OS X v10.6或v10.7 (64-bit applications),iOS4或iOS5。注意:其中Mac OS X v10.6和iOS4不支持weak references(弱引用,后面会说明什么是weak references)。

Xcode 4.2提供了一个名为“Convert to Objective-C Automatic Reference Counting”的工具,在Edit->Refactor->Convert to Objective C ARC... menu下,可以帮你自动将使用Manual Reference Counting的老代码转换成使用ARC的新代码(例如去掉对retain和release的调用)。


使用ARC的一些规则:

1、不能直接调用dealloc方法,不能重载或直接调用retain,release,retainCount,或autorelease等方法。但可以通过@selector(retain),@selector(release)这样的形式调用。

2、用户自定义的dealloc方法,不能调用[super dealloc],编译器会自动帮你添加这个代码。

3、对Core Foundation-style的对象,仍可以使用CFRetain, CFRelease等方法。 不能使用NSAllocateObject或NSDeallocateObject去创建对象,请使用alloc方法。

4、在c语言中的结构体中,不能再使用对象指针。请放弃C结构体,使用Objective-C的类。

5、id和void*之间没有隐式的类型转换,请使用显式类型转换。 不能使用NSAutoreleasePool,ARC提供了@autoreleasepool语句块。

6、不能使用NSZone。 方法和变量的命名不能以“new”开头。

7、关于对象的生命周期:

      weak 引用:设置成weak的属性,不会影响对象的生命周期,如果引用的对象已经被释放,引用会指向nil。

      strong引用:设置成strong的属性,会影响对象的生命周期。

      例如:@property(strong) MyClass *myObject; 和                  @property(retain) MyClass *myObject;是等效的。
                  @property(weak) MyClass *myObject;和                  @property(assign) MyClass *myObject; 
 8、可用的限定词:
 __strong, 默认的 __weak __unsafe_unretained,和weak的区别是当对象被释放时,引用不指向nil。
__autoreleasing,当方法的参数是id*,且希望方法返回时对象被autoreleased,可以添加__autoreleasing限定词。
使用__weak时要特别小心,例如
  1. NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];   
  2. NSLog(@"string: %@", string); //此时string为空,因为weak类型不影响对象的生命周期,对象刚创建就释放了。

其他特性: 使用strong, weak, autoreleasing限定的变量会被隐式初始化为nil。


=======================================================================================================

Xcode 4.2: 点击项目后,

Build Settings -> Apple LLVM compiler 3.0 - Language -> Objective-C Automatic Referencing Counting, 默认是YES 设置为NO即可。



在新发布的ios5中,有个很吸引眼球的特性就是“Automatic Reference Counting”,简单来说就是内存自动回收,看起来似乎是平时开发中遇到的各种内存问题的福音,仔细了解了一下,似乎没有那么美好:

1。 需要iOS5才支持

2。 很多引用的类库暂时还不支持.麻烦的是对大多数第三方库需要加禁用arc的编译flag,因为大多都因为兼容性还在使用手动内存管理。

由于 iOS5 xcode4.2 引入了ARC (AutomicReferenceCounting) , 使用xcode4.2 新建项目时,会有一些小小的变化。 NSAutoReleasePool 被 @ {Autoreleasepool / / Code for autoreleasepool } block 取代了。

新增了__strong , __weak 编译指令。

ios5.0知道你的变量在何时需要release,何时需要autorelease,所以变量不要写成全局的,全局的变量用single去代替。

而且当你开启了ARC后, 如果使用传统的手工 release 就是报错 'release' is unavailable: not available in automatic reference counting modeAutomatic Reference Counting forbids explicit message send of 'release'

你可以按照如下方法关闭它

Xcode 4.2: 点击项目后,

Build Settings -> Apple LLVM compiler 3.0 - Language -> Objective-C Automatic Referencing Counting, 默认是YES 设置为NO即可。

[attachment=385]

但实际上 ARC确实比手动释放快,而且不会发生内存泄漏的情况,具体可以参考这里

http://clang.llvm.org/docs/AutomaticReferenceCounting.html

http://stackoverflow.com/questions/6385212/how-does-the-new-automatic-reference-counting-mechanism-work

一篇深入讨论 ARC的文章

http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/


==================================================================================

iOS应用开发:ARC之@property使用


所有者属性

我们先来看看与所有权有关系的属性,关键字间的对应关系。

属性值关键字所有权strong__strong有weak__weak无unsafe_unretained__unsafe_unretained无copy__strong有assign__unsafe_unretained无retain__strong有

strong

该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者。

weak

该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被破弃之后,对象将被自动赋值nil。

并且,delegate 和 Outlet 应该用 weak 属性来声明。同时,如上一回介绍的 iOS 5 之前的版本是没有 __weak 关键字的,所以 weak 属性是不能使用的。这种情况我们使用 unsafe_unretained。

unsafe_unretained

等效于__unsafe_unretaind关键字声明的变量;像上面说明的,iOS 5之前的系统用该属性代替 weak 来使用。

copy

与 strong 的区别是声明变量是拷贝对象的持有者。

assign

一般Scalar Varible用该属性声明,比如,int, BOOL。

retain

该属性与 strong 一致;只是可读性更强一些。

读写相关的属性 (readwrite, readonly)

读写相关的属性有 readwrite 和 readonly 两种,如果使用ARC之后,我么需要注意一下 readonly 属性的使用。

比如下面的变量声明。

  1. @property (nonatomic, readonly) NSString *name;  

一般声明为 readonly 的变量按理说应该不需要持有所有权了,但是在ARC有效的情况下,将出现下面的错误信息 :

 “ARC forbids synthesizing a property of an Objective-C object with unspecified ownership or storage attribute如果定义了ARC有效,那么必须要有所有者属性的定义;所以我们的代码改成这样,就OK了
  1. @property (nonatomic, strong, readonly) NSString *name; 

不过有一点,Scalar Varible的变量缺省都有 assign 的属性定义,所以不需要给他们单独的明示声明了。


 

原创粉丝点击