1. id 與 NSObject *
(1) id 是 Objective-C 對象,但是並不一定是NSObject對象,並非所有的Foundation/Cocoa對象都是繼承於NSObject對象的,比如NSProxy。同時,id與NSObject對象之間有很多的共同方法,比如retain與release等方法。更一步來說:所有的對象本質來說都是 id 類型的。
(2) 對於id來說,你可以調用任意可見的selector,編譯器和IDE不會進行類型檢查,這個時候就需要你自己進行類型檢查並且進行類型轉換,來確保這些調用不會出錯。而對於NSObject *類型,只能調用NSObject對象所聲明的selector,不能調用它子類的selector,編譯器會進行檢查。
(3) 對於一些不想或者不能進行類型檢查的地方,可以使用id。比如在集合(array, collection)類型中,比如在一些你並不知道方法的返回類型的地方(比如alloc),比如我們經常聲明delegate為id類型,在運行的時候再使用respondToSelector:來進行檢查。
2. id<NSObject>
使用id<NSObject>來聲明一個對象,相當於告訴編譯我們並不知道這個對象的類型,但是它實現NSObject protocol。一個這種類型的指針,即可以用來指向NSObject*對象,也可以用來指向NSProxy*對象,因為NSObject對象與NSProxy對象都是現了NSObject protocol。
3. id 與 instancetype
在instancetype有效的情況下,應該盡量去使用instancetype。至於什麼是合適的時候,可以參考stack overflow上面所說:“Use instancetype whenever it's appropriate, which is whenever a class returns an instance of that same class.”,http://stackoverflow.com/questions/8972221/would-it-be-beneficial-to-begin-using-instancetype-instead-of-id/14652187#14652187
Apple官方文檔:
In your code, replace occurrences of
id
as a return value with
instancetype
where appropriate. This is typically the case for
init
methods and class factory methods. Even though the compiler automatically converts methods that begin with “alloc,” “init,” or “new” and have a return type of
id
to return
instancetype
, it doesn’t convert other methods. Objective-C convention is to write
instancetype
explicitly for all methods.
Emphasis mine. Source: Adopting Modern Objective-C