iOS大神留步,你確定你會使用id和instancetype?
寫了那么多代碼,懂了那么多道理,可是我就問你一句:id和instancetype的使用你懂了嗎?
1.
- (instancetype)init{
self = [super init ];
if (self) {
}
return self;
}
2.
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:(CGRect)frame];
if (self) {
}
return self;
}
上述的兩處代碼我們經常在使用,但是有多少人知道這里的instancetype返回值表示什么意思?這里為什么用的instancetype而不用id?這里用id又會怎么樣?
要搞懂id 和instancetype的異同 首先要弄懂iOS中兩個概念:關聯返回類型/非關聯返回類型
根據Cocoa的命名規則,滿足下述規則的方法:
1、類方法中,以alloc或new開頭
2、實例方法中,以autorelease,init,retain或self開頭
會返回一個方法所在類類型的對象,這些方法就被稱為是關聯返回類型的方法。換句話說,這些方法的返回結果以方法所在的類為類型,概念有點繞口,請看下面的例子
@interface NSObject
+ (id)alloc;
- (id)init;
@end
@interface NSArray : NSObject
@end
當我們使用如下方式初始化NSArray時
NSArray *array = [[NSArray alloc] init];
按照Cocoa的命名規則,語句[NSArray alloc]的返回類型就是NSArray*因為alloc的返回類型屬于關聯返回類型。同樣,[[NSArray alloc]init]的返回結果也是NSArray*。
到這里還沒看懂的[捂臉][捂臉][捂臉],沒關系我也是看了兩遍才看懂什么意思,多看幾遍就懂了。
既然關聯返回類型是類方法中以alloc或new開頭 實例方法中以autorelease,init,retain或self開頭的,那么非關聯返回類型肯定就是相反的定義了。舉個例子吧
@interface NSArray
+ (id)constructAnArray;
@end
根據Cocoa的命名規則,這個肯定就不是關聯返回類型,那一定就是非關聯返回類型了
當我們使用如下方式初始化NSArray時:[NSArray constructAnArray];
根據Cocoa的方法命名規范,得到的返回類型就和方法聲明的返回類型一樣,是id。(重點:因為它不符合關聯返回類型命名規范)
對上面的返回類型我們做一點修改
但是如果使用instancetype作為返回類型,如下:
@interface NSArray
+ (instancetype)constructAnArray;
@end
我們使用instancetype做返回類型
當使用相同方式初始化NSArray時:[NSArray constructAnArray]; 得到的返回類型和方法所在類的類型相同,是NSArray*
到這里就已經可以對比出來id和instancetype的異同了
總結一下,instancetype的作用,就是使那些非關聯返回類型的方法返回所在類的類型!
為什么要使用instancetype?
能夠確定對象的類型,能夠幫助編譯器更好的為我們定位代碼書寫問題,比如:
[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`"
[[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error)
上例中第一行代碼,由于[[NSArray alloc]init]的結果是NSArray*,這樣編譯器就能夠根據返回的數據類型檢測出NSArray是否實現mediaPlaybackAllowsAirPlay方法。有利于開發者在編譯階段發現錯誤。
第二行代碼,由于array不屬于關聯返回類型方法,[NSArray array]返回的是id類型,編譯器不知道id類型的對象是否實現了mediaPlaybackAllowsAirPlay方法,也就不能夠替開發者及時發現錯誤。
instancetype和id的異同
1、相同點
都可以作為方法的返回類型
2、不同點
①instancetype可以返回和方法所在類相同類型的對象,id只能返回未知類型的對象;
②instancetype只能作為返回值,不能像id那樣作為參數,比如下面的寫法:
//err,expected a type
- (void)setValue:(instancetype)value
{
//do something
}
就是錯的,應該寫成:
- (void)setValue:(id)value
{
//do something
}
來自:http://www.jianshu.com/p/37c0060fbe27