ARC学习笔记

1. ARC并不是自动管理内存,与AutoreleasePool不同,ARC是LLVM 3.0编译器提供的特性,编译器自动在适当的地方插入retain、release、autorelease,所以还是手动管理内存,对象不会像AutoreleasePool一样在内存中存放很久。

2. ARC只能工作于Objective-C对象,如果应用使用了Core Foundation或malloc()/free(),此时需要你来管理内存。

3. 虽然ARC管理retain和release,但并不表示不需要处理内存问题,strong指针会保持对象的生命,所以有时候为了回收内存,自己要将其设为nil,以便释放内存,否则内存可能会被用光。

4. property的修饰符有一定变化。a)strong等同于retain;b)weak是弱指针,当对象释放时会自动设置为nil;c)unsafe_unretained等同于assign只有iOS4才应该使用;d)copy和以前的copy一样,复制一个对象并创建strong关联;e)assign不能用于对象,应该用于BOOL、int和float等值类型。

5. 如果dealloc方法只是释放对象,则不需要此方法,但如果dealloc中处理了其它非内存资源释放,如定时器、Core Foundation对象,则仍然需要在dealloc方法中进行手动释放,但不能调用[super dealloc]。

6. 由于ARC只作用于Objective-C对象,有时候要用到Core Foundation对象,两者之间的转换可以使用toll-free bridging来很方便地完成,例如NSString和CFStringRef。编译器必须知道由谁来负责释放转换后的对象,如果你把一个Objective-C对象当作Core Foundation对象来使用,ARC将不再负责释放该对象,在两种对象之间进行转换时,要显示地移交或者接受权利。

7. 函数参数和局部变量一样,都是strong指针,这种对象在函数入口处会被retain,并且对象会持续存在直到指针被销毁。

8. 

1 - (NSString *)escape:(NSString *)text {
2     return [(NSString *)CFURLCreateStringByAddingPercentEscapes(
3                         NULL,
4                         (CFStringRef)text, // 这里需要进行bridging casts,将text临时当作CFStringRef对象来使用。
5                         NULL,
6                         (CFStringRef)@"!*'();:@&=+$,/?%#[]", // 这里不用bridging casts,因为这是常量,不需要释放!
7                         CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) 
8             autorelease];
9 }

 

9. __bridge转换不仅仅局限于Core Foundation对象,某些API使用void *指针作为参数,允许你传递任何东西的引用,比如Objective-C对象、Core Foundation对象或malloc()内存缓冲区等等。那么传参数的时候将这些对象转换为void *,如:[UIView beginAnimations:nil context:(__bridge void *)someObject],在使用这些参数的地方再将其转换回来,如:MyClass *myObject = (__bridge MyClass *)context。

10. 内存管理权的移交有三种情况,a)使用CFBridgingRelease()或__bridge_transfer将管理仅移交给Objective-C;b)使用CFBridgingRetain()或__bridge_retained将管理权移交给Core Foundation;c)使用__bridge来临时使用某对象,不改变管理权。

11. 在ARC之前只有成员变量才会默认设为nil,在arc中局部对象指针会被设为nil,局部值类型和值类型指针还是随机数。

12. 所有的Core Foundation对象类型都与Objective-C能够toll-free bridged,但是UIColor不能,因为UIColor与CGColor并不是toll-free bridged,所以把CGColor放入NSArray要强制转换为id类型。

13. property中的属性名不能以new开头,除非将getter指定指定为另外一个名字,@property NSString *newTitle;会出错,@property (getter=theNewTitle) NSString *newTitle;正确。

14. autorelease pool变成了一种语言结构,而不是以前的类,@autoreleasepool{}比NSAutoreleasePool快六倍。在一个很大的循环中,有时候循环xx次进行一次NSAutoreleasePool清除工作,但其实这是不必要的,每循环一次清一次也无所谓,现在@autoreleasepool指令比NSAutoreleasePool快六倍,在循环中直接使用也不用担心性能问题。

15. block会捕获自己使用到的所有变量,如果用到成员变量,那么成员变量所在的类会被retain,这样这个类就不会被释放,解决办法是使用局部变量,NSString *text = self.artistName;,然后在block中使用text,而不是self.artistName,就不会出现问题。

16. 有时候block避免不了使用self对象,ARC以前可以创建一个局部的__block对象,把self值赋值过去,如:__block MyClass *blockSelf = self;,在block中引用这个__block局部变量来访问self的属性都不会retain self,但是在ARC中即使使用了__block来标记这个局部变量,它也是强引用的,这时__block的唯一功能是允许你修改已捕获的变量。ARC的解决办法是定义弱引用:__weak MyClass *weakSelf = self;,这样weakSelf引用了self,但不进行retain,在block中捕获weakSelf而不是self,因此不存在所有权回环。在简单应用中block属于self,所以block不可能在self被释放后还能被调用,有时候在block中检查这个weakSelf被认为是不必要的,但是如果block被异步调用,则创建强引用来保持对象存活就有必要了,因此在ARC中使用block,而且要避免捕获self,可以这样:

 1 - (void)doSomething
 2 {
 3     __weak weakSelf = self;
 4     block = ^() {
 5         id strongSelf = weakSelf;
 6         if ( strongSelf != nil ) {
 7             // do stuff with strongSelf
 8         }
 9     };
10 }

 

17. 如果创建一个对象,等待5秒后执行某一block,然后释放掉该对象,在ARC以前应该这样:

1 - (void)doSomething
2 {
3     MyClass *object = [[MyClass alloc] init];
4     object.block = ^(void) {
5         // do stuff
6         [object autorelease];
7     };
8     [object launchAfter:5];
9 }

 

在ARC中不允许使用autorelease,所以去掉释放那一行,那么这样会导致block永远不会被执行,因为object对象在此函数返回后被释放。解决办法是定义__block类型变量,这种类型是强引用,且block中能修改其值,然后在block中将些变量设为nil,如下:

1 - (void)doSomething
2 {
3     __block MyClass *object = [[MyClass alloc] init];
4     object.block = ^(void) {
5         // do stuff
6         object = nil;
7     };
8     [object launchAfter:5];
9 }

 

18. 

1 - (void)doSomething
2 {
3     NSString *string;
4     @autoreleasepool {
5         string = [NSString stringWithFormat:…];
6     }
7     // the string object is still alive here
8 }

 

19. 

1 - (void)doSomething
2 {
3     __autoreleasing NSString *string;
4     @autoreleasepool {
5         string = [NSString stringWithFormat:…];
6     }
7     // the string object is still deallocated here
8     NSLog(@"%@", string); // crash!
9 }

 

20. 编写自己的out-parameter方法:

 1 - (NSString *)fetchKeyAndValue:(__autoreleasing NSNumber **)theValue
 2 {
 3     NSString *theKey;
 4     NSNumber *theValue;
 5     
 6     // do whatever you need to do here
 7     
 8     *value = theValue;
 9     return theKey;
10 }

 

21. Core Foundation对象不能autorelease,autorelease完全纯属于Objective-C,有些人通过转换Core Foundation对象为id,再调用autorelease,这在ARC中明显不能工作,因为不能调用autorelease。

posted @ 2013-04-17 01:25  HaipingWuiOS  阅读(803)  评论(0编辑  收藏  举报