Objective-C中有一些很有趣的數據類型經常會被錯誤地理解。他們中的大多數都可以在/usr/include/objc/objc.h或者這個目錄中的其他頭文件中找到。下面是從objc.h中摘錄的一段,定義了一些數據類型:
// objc.h
typedef struct objc_class*Class;
typedef struct objc_object{
Class isa;
} *id;
typedef struct objc_selector*SEL;
typedef id (*IMP)(id,SEL, …);
typedef signed char BOOL;
#define YES(BOOL)1
#define NO(BOOL)0
#ifndef Nil
#define Nil 0
#endif
#ifndef nil
#define nil 0
#endif
id
id和void *並非完全一樣。在上面的代碼中,id是指向struct objc_object的一個指針,這個意思基本上是說,id是一個指向任何一個繼承了Object(或者NSObject)類的對象。需要注意的是id是一個指針,所以你在使用id的時候不需要加星號。比如id foo=nil定義了一個nil指針,這個指針指向NSObject的一個任意子類。而id *foo=nil則定義了一個指針,這個指針指向另一個指針,被指向的這個指針指向NSObject的一個子類。
nil
nil和C語言的NULL相同,在objc/objc.h中定義。nil表示一個Objctive-C對象,這個對象的指針指向空(沒有東西就是空)。
Nil
首字母大寫的Nil和nil有一點不一樣,Nil定義一個指向空的類(是Class,而不是對象)。
NULL: A null pointer to anything else, is for C-style memory pointers. 用於對非對象指針賦空值,比如C指針
NSNull :對於像NSArray這樣的類型,nil或NULL不能做爲加到其中的Object,如果定義了一個NSArray,爲其分配了內存,又想設置其中的內容爲空,則可以用[NSNULL null】返回的對象來初始化NSArray中的內容。
SEL
這個很有趣。SEL是“selector”的一個類型,表示一個方法的名字。比如以下方法:
-[Foocount] 和 -[Barcount] 使用同一個selector,它們的selector叫做count。
在上面的頭文件裏我們看到,SEL是指向struct objc_selector的指針,但是objc_selector是什麼呢?那麼實際上,你使用GNU Objective-C的運行時間庫和NeXT Objective-C的運行運行時間庫(Mac OS X使用NeXT的運行時間庫)時,它們的定義是不一樣的。實際上Mac OSX僅僅將SEL映射爲C字符串。比如,我們定義一個Foo的類,這個類帶有一個- (int) blah方法,那麼以下代碼:
NSLog (@"SEL=%s",@selector(blah));
會輸出爲 SEL=blah。
說白了SEL就是返回方法名。
IMP
從上面的頭文件中我們可以看到,IMP定義爲id (*IMP) (id,SEL, …)。這樣說來,IMP是一個指向函數的指針,這個被指向的函數包括id(“self”指針),調用的SEL(方法名),再加上一些其他參數。
說白了IMP就是實現方法。
Method
在objc/objc-class.h中定義了叫做Method的類型,是這樣定義的:
typedef struct objc_method*Method;
struct objc_method{
SEL method_name;
char *method_types;
IMP method_imp;
};
這個定義看上去包括了我們上面說過的其他類型。也就是說,Method(我們常說的方法)表示一種類型,這種類型與selector和實現(implementation)相關。
Class
從上文的定義看,Class(類)被定義爲一個指向struct objc_class的指針,在objc/objc-class.h中它是這麼定義的:
struct objc_class{
struct objc_class*isa;
struct objc_class*super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list*ivars;
struct objc_method_list**methodLists;
struct objc_cache*cache;
struct objc_protocol_list*protocols;
};