多年來布持,Objective-C語言已經(jīng)有了革命性的發(fā)展余境。雖然核心理念和實踐保持不變,但語言中的部分內(nèi)容經(jīng)歷了重大的變化和改進』偕現(xiàn)代化的Objective-C在類型安全践磅、內(nèi)存管理、性能灸异、和其他方面都得到了增強府适。使你更容易編寫正確的代碼。在你現(xiàn)有和未來的代碼中使用這些改進是很重要的肺樟,會使你的代碼一致檐春、可讀、靈活么伯。
Xcode提供了一個工具來幫助做這些結(jié)構(gòu)性的變化喇聊。但在使用這個工具之前,你想了解工具為你的代碼做了什么改變以及為什么蹦狂。本文強調(diào)了一些最重要的和有用的現(xiàn)代化方式可以用在你的代碼中誓篱。
instancetype
使用instancetype關(guān)鍵字作為返回類型的方法,該方法返回一個類的實例(或該類的子類)這些方法包括alloc,init,和類工廠方法凯楔。
使用instancetype代替id在適當(dāng)?shù)牡胤娇梢愿纳芆bjective-C代碼類型安全窜骄。例如:考慮下面的代碼:
@interface MyObject : NSObject
+ (instancetype)factoryMethodA;
+ (id)factoryMethodB;
@end
@implementation MyObject
+ (instancetype)factoryMethodA
{
return [[[self class] alloc] init];
}
+ (id)factoryMethodB
{
return [[[self class] alloc] init];
}
@end
void doSomething()
{
NSUinteger x, y;
// Return type of +factoryMethodA is taken to be "MyObject *"
x = [[MyObject factoryMethodA] count];
// Return type fo +factoryMethodB is "id"
y = [[MyObject factoryMethodB] count];
}
因為+factoryMethodA使用了instancetype作為返回類型,該消息的類型
表達式為MyObject *.當(dāng)MyObject沒有-count方法的時候摆屯,編譯器會發(fā)出警告的在x行:
main.m: 'MyObject' may not respond to 'count'
然而邻遏,由于+factoryMethodB返回類型為id,編譯器不可以給出警告虐骑。因為一個id可以是任何類型的對象類准验,由于存在一個名為-count的方法在一些類中,編譯器可能返回一個+factoryMehtodB的實現(xiàn)的方法廷没。
確保instancetype工廠方法有權(quán)利子類化行為糊饱,在初始化的時候一定要使用
[self class]
而不是直接引用的類名。遵循這個慣例確保編譯器將正確判斷出子類的類型颠黎。例如:考慮嘗試這樣做一個MyObject的子類從前面的示例:
@interface MyObjectSubclass : MyObject
@end
void doSomethingElse()
{
NSString *aString = [MyObjectSubclass factoryMethodA];
}
關(guān)于這個代碼編譯器將給出下面的警告:
main.m: Incompatible pointer types initializing 'NSString *'
with an expression of type 'MyObjectSubclass *'
在這個例子中,+factoryMethodA MyObjectSubclass類型的消息發(fā)送返回一個對象,這是接收者的類型另锋。編譯器確定適當(dāng)?shù)姆祷仡愋?factoryMethodA應(yīng)該是MyObjectSubclass子類,而不是超類的工廠方法被調(diào)用狭归。
怎樣適配
在你的代碼中,出現(xiàn)id作為返回值替換為instancetype在適當(dāng)?shù)牡胤截财骸_@通常是init方法和類的工廠方法。甚至編譯器會自動轉(zhuǎn)以“alloc”过椎、“init”室梅、“new”開頭的方法,而不轉(zhuǎn)換其他的方法。objective-c對instancetype的轉(zhuǎn)換是顯式的方式亡鼠。
請注意,您僅應(yīng)該用instancetype替換id作為返回值,而不是在你的代碼的任何地方都這么做赏殃。不像id,instancetype在聲明方法時僅僅只能作為返回值類型使用拆宛。
例如:
@interface MyObject
- (id)myFactoryMethod;
@end
應(yīng)該變?yōu)椋? @interface MyObject
- (instancetype)myFactoryMethod;
@end
或者,您可以在Xcode使用現(xiàn)代objective-c變換器自動進行轉(zhuǎn)換您的代碼嗓奢。更多信息請看使用Xcode重構(gòu)你的代碼讼撒。