- 什么是ARC?
ARC是Automatic Reference Counting自动引用计数的简称.
ARC不是Runtime model,不会自动处理malloc/free, new/delete, CF等,不是垃圾回收机制.
ARC是依赖于编译器的,对Objective-C对象的自动内存管理机制(新的weak指针特性涉及到runtime)。 - ARC是如何工作的?
编译器根据规则自动添加retain, release, autorelease等进行编译。 - 我们的项目需要转到ARC吗?
答案是“YES”, ARC是编译期完成的,并且编译器还进行了很多优化,性能没有影响。最重要的是我们不需要花费大量精力去寻找由于手写造成的内存泄漏了。咱们还是多花点时间完成产品功能吧。 -
ARC需要注意的几点
1) 不允许调用或者实现retain/release/autorelease方法,dealloc方法也不需要调用,但是如果确实需要在dealloc时完成某些清理工作,比如保存数据,可以实现dealloc方法,但是不需要调用[super dealloc], 交给系统去调用。
2) 不要在C或者C++的结构体或者容器中存放Objective-C对象struct Pair{ NSString *name; // retained int value; } Pair *p = malloc…; … free(p); //由于ARC不适用于malloc, free,所以不会自动调用[p->name release], 这里会有内存泄漏。
3) 不要随意转换OC对象和CF指针。可以按照以下方式转换:
//将NSString对象A转换成W,注意内存管理权不变化,即当A对象被ARC释放时,W指向的即是1个野指针; CFStringRef W = (__bridge CFStringRef)A; //反过来将CFStringRef对象B转成NSString *X,内存管理权同样不会发生变化,ARC不会为X自动调用release方法,当通过CFRelease释放B后,X对象是非法的了。 NSString *X = (__bridge NSString*)B; 将NSString对象C转换成Y,同时调用了1次retain操作,假设原来引用计数是1,这次后就是2,C由ARC负责release,Y需要手动CFRelease,都执行完后,计数为1,内存释放 CFStringRef Y = (__bridge_retain CFStringRef)C; //反过来将CFStringRef对象D转成NSString *Z,内存管理权发生变化,内存对象的引用计数仍然为1,但是由Z持有,ARC负责Z的release,不允许CFRelease D了。 NSString *Z = (__bridge_transfer NSString*)D;
4)不允许使用NSAutoreleaePool
由@autoreleasepool{…}替换 -
引用类型
1) strong __strong
默认所有变量都是strong类型,strong相当于原来的retain属性。比如:@property(noatomic, strong) NSString *name 等价于原来的:@property(noatomic, retain) NSString *name
局部变量,NSString *name等价于__strong NSString *name; 在离开name的作用域前,编译器会自动填入[name release]
2) autorelease __autoreleasing
这个用途比较特殊,用于传出参数,写程序的时候不需要显示声明。-(void) runWithError:(NSError **)error{ *error = …; }
在编译器处理后如下:
-(void) runWithError:(__autoreleasing NSError **)error{ *error = [[... retain] autorelease]; }
3) unsafe __unsafe_unretained
非常传统的赋值方式,类似于assign property__unsafe_unretained NSString *unsafeName = name;
当name被ARC release后,若ref count=0, unsafeName指向的可能就是非法内存了。
4) weak __weak
__weak标示的变量指向的对象如果被dealloc,那么__weak变量立即变为nil,由Runtime负责修改值。 __weak NSString *safeName = name;// name对象释放后,safeName为nil注意:weak和unsafe需要显示声明。 -
返回值的一些命名规则
1)普通返回都是autorelease的-(NSString*)serial{ return _serial; } 等价于: -(NSString*)serial{ NSString *returnValue = [_serial retain]; return [returnValue autorelease]; }
2)以new开头返回的是retain的对象
- (NSString*)newSerial{ return _serial; } 等价于: -(NSString*)newSerial{ NSString *returnValue = [_serial retain]; return returnValue; } 不过不用担心,即使是以new开头返回也不会有内存泄漏,比如: - (void)logSerial{ NSLog(“%@”, [self newSerial]);} 等价于: - (void)logSerial{ NSString *returnValue = [self newSerial]; NSLog(“%@”, returnValue); [returnValue release]; //使用过后立即释放 } 不过说实在话,基本上很少用new开头的。
-
如何兼容ARC和Non-ARC版本
#if __has_feature(objc_arc) #define BRIDGE_CAST __bridge #define MRC_RETAIN(x) (x) #define MRC_RELEASE(x) #define MRC_AUTORELEASE(x) (x) #else #define BRIDGE_CAST #define MRC_RETAIN(x) [x retain] #define MRC_RELEASE(x) [x release]; x = nil #define MRC_AUTORELEASE(x) [x autorelease] #endif
浅析ARC
最新推荐文章于 2021-08-08 22:29:54 发布