iOS 对arc的一点深入理解

基于简化开发的思想来看,ARC绝对是一个没理由拒绝的技术进步。

 

ARC随着iOS5问世,到现在的iOS8,你还在手动写retain,release么?除了固守思想外,对ARC的恐惧大都来自对它的未知。

 

比如我在公司尝试说服team使用ARC时被质疑的几个问题:

 

ARC和Java的GC一样,会导致一部分性能损耗?

 

首先,ARC和GC是两码事,ARC是编译时编译器“帮你”插入了原本需要自己手写的内存管理代码,而非像GC一样运行时的垃圾回收系统。

 

ARC内存不知道什么时候释放,导致不可控的内存涨落?

 

了解ARC的原理后,就知道,ARC下编译器插入的内存管理的代码是经过优化的,对于使用完的内存,多运行一行代码都不会浪费,可以这么说,手写的内存管理必须达到很严谨的水平才可能达到ARC自动生成的一样完整且没有疏漏。

 

ARC下面自己不管理内存,很不爽,很没有安全感。

 

这纯粹是习惯的问题了,开发者的目标是用最简化的手段完成一个最可靠的程序,进步需要改变的。好在编译选项中提供了-fobjc-arc和-fno-objc-arc来保证整个的变革的继续下去,就像社会主义中国里的港澳。

 

ARC的约定

 

使用ARC之后一个费解的地方是,一个方法生成的对象,没有任何附加标示,ARC怎么知道生成的对象是不是autorelease的呢?

  1. @interface Sark : NSObject  
  2. + (instancetype)sarkWithMark:(NSString *)mark; // 1  
  3. - (instancetype)initWithMark:(NSString *)mark; // 2  
  4. @end 

 

这是非ARC时常用的手段,1、生成autorelease对象,2、生成普通对象,而现在ARC不能调用autorelease,使用时怎么能知道呢?

 

  1. {  
  2.     // ...  
  3.     Sark *sark1 = [Sark sarkWithMark:@"萨萨萨"];  
  4.     Sark *sark2 = [[Sark alloc] initWithMark:@"萨萨萨"];  

使用约定,NS定义了下面三个编译属性

 

  1. #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))  
  2. #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))  
  3. #define NS_RETURNS_INNER_POINTER __attribute__((objc_returns_inner_pointer))  

这三个属性是Clang自己使用的标示,除非特殊情况不要自己使用,但是这些对理解ARC是很有帮助的。

 

这里还要介绍一个概念,Method family:

 

An Objective-C method may fall into a method family, which is a conventional set of behaviors ascribed to it by the Cocoa conventions.

 

指的是命名上表示一类型的方法,比如- init和- initWithMark:都属于init的family

 

于是乎,编译器约定,对于alloc,init,copy,mutableCopy,new这几个家族的方法,后面默认加NS_RETURNS_RETAINED标识;而其他不指名标识的family的方法默认添加NS_RETURNS_NOT_RETAINED标识


也就是说刚才的方法,在编译器看来是这样的:

  1. @interface Sark : NSObject  
  2. + (instancetype)sarkWithMark:(NSString *)mark NS_RETURNS_NOT_RETAINED; // 1  
  3. - (instancetype)initWithMark:(NSString *)mark NS_RETURNS_RETAINED; // 2  
  4. @end 

 

这也就是为什么ARC下面,不能把一个属性定义成名字是这样的:

 

  1. @property (nonatomic, copy) NSString *newString; // 编译器不允许 

- newString就成了new家族的方法,内存就不对了

对于NS_RETURNS_INNER_POINTER这货,主要使用在返回的是一个对象的内部C指针的情况,如NSString的方法:

 

    1. - (__strong const char *)UTF8String NS_RETURNS_INNER_POINTER; 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值