Objective-C語言是一門動態語言,它將很多靜態語言在編譯和鏈接時期做的事放到了運行時來處理。這種動態語言的優勢在於:我們寫代碼時更具靈活性,如我們可以把消息轉發給我們想要的對象,或者隨意交換一個方法的實現等。
Objective-C類是由Class類型來表示的,它實際上是一個指向objc_class結構體的指針。它的定義如下:
typedef struct objc_class *Class;
查看objc/runtime.h中objc_class結構體的定義如下:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE; // 父類
const char *name OBJC2_UNAVAILABLE; // 類名
long version OBJC2_UNAVAILABLE; // 類的版本信息,默認為0
long info OBJC2_UNAVAILABLE; // 類信息,供運行期使用的一些位標識
long instance_size OBJC2_UNAVAILABLE; // 該類的實例變量大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 該類的成員變量鏈表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定義的鏈表
struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法緩存
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 協議鏈表
#endif
} OBJC2_UNAVAILABLE;
1、
常用舉例
Class newClass = objc_allocateClassPair([NSError class], "TestClass", 0); // 創建新的類
參數1: 父類
參數2: 子類名
參數3: extraBytes
class_addMethod(newClass, @selector(testMetaClass), (IMP)TestMetaClass, "v@:"); // 為新的類添加方法
參數1: 類名
參數2: 方法名稱
參數3: 方法(IMP)你寫的方法名
參數4: 一個定義該函數返回值類型和參數類型的字符串 根據返回值和參數動態的確定 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html 這裡可以查看對應返回值類型的表達方法 v表示void 後邊的:後邊表示參數 比如說 定義 int:(id self, SEL _cmd,NSString * name) 那麼就是 i@:@ 這樣的。
objc_registerClassPair(newClass); // 注冊創建的類
id instance = [[newClass alloc] initWithDomain:@"some domain" code:0 userInfo:nil]; // 實例化對象
[instance performSelector:@selector(testMetaClass)]; // 調用方法
// 獲取類的類名 const char * class_getName ( Class cls );
// 獲取類的父類 Class class_getSuperclass ( Class cls ); // 判斷給定的Class是否是一個元類 BOOL class_isMetaClass ( Class cls );
// 獲取實例大小
size_t class_getInstanceSize ( Class cls );
在objc_class中,所有的成員變量、屬性的信息是放在鏈表ivars中的。ivars是一個
// 獲取類中指定名稱實例成員變量的信息 Ivar class_getInstanceVariable ( Class cls, const char *name ); // 獲取類成員變量的信息 Ivar class_getClassVariable ( Class cls, const char *name ); // 添加成員變量 BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types ); // 獲取整個成員變量列表 Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
class_copyIvarList函數,它返回一個指向成員變量信息的數組,數組中每個元素是指向該成員變量信息的objc_ivar結構體的指針。這個數組不包含在父類中聲明的變量。outCount指針返回數組的大小。需要注意的是,我們必須使用free()來釋放這個數組
// 獲取指定的屬性 objc_property_t class_getProperty ( Class cls, const char *name ); // 獲取屬性列表 objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount ); // 為類添加屬性 BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount ); // 替換類的屬性 void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
// 添加方法
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types );
// 獲取實例方法
Method class_getInstanceMethod ( Class cls, SEL name );
// 獲取類方法
Method class_getClassMethod ( Class cls, SEL name );
// 獲取所有方法的數組
Method * class_copyMethodList ( Class cls, unsigned int *outCount );
// 替代方法的實現
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );
// 返回方法的具體實現
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );
// 類實例是否響應指定的selector
BOOL class_respondsToSelector ( Class cls, SEL sel );
class_addMethod的實現會覆蓋父類的方法實現,但不會取代本類中已存在的實現,如果本類中包含一個同名的實現,則函數會返回NO。如果要修改已存在實現,可以使用method_setImplementation。一個Objective-C方法是一個簡單的C函數,它至少包含兩個參數—self和_cmd。所以,我們的實現函數(IMP參數指向的函數)至少需要兩個參數,如下所示:
void myMethodIMP(id self, SEL _cmd) { // implementation .... }
// 添加協議 BOOL class_addProtocol ( Class cls, Protocol *protocol ); // 返回類是否實現指定的協議 BOOL class_conformsToProtocol ( Class cls, Protocol *protocol ); // 返回類實現的協議列表 Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );
// 獲取版本號 int class_getVersion ( Class cls ); // 設置版本號 void class_setVersion ( Class cls, int version );
// 創建一個新類和元類 Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes ); // 銷毀一個類及其相關聯的類 void objc_disposeClassPair ( Class cls ); // 在應用中注冊由objc_allocateClassPair創建的類 void objc_registerClassPair ( Class cls );
// 創建類實例 id class_createInstance ( Class cls, size_t extraBytes ); // 在指定位置創建類實例 id objc_constructInstance ( Class cls, void *bytes ); // 銷毀類實例 void * objc_destructInstance ( id obj );
// 返回指定對象的一份拷貝 id object_copy ( id obj, size_t size ); // 釋放指定對象占用的內存 id object_dispose ( id obj );
// 修改類實例的實例變量的值 Ivar object_setInstanceVariable ( id obj, const char *name, void *value ); // 獲取對象實例變量的值 Ivar object_getInstanceVariable ( id obj, const char *name, void **outValue ); // 返回指向給定對象分配的任何額外字節的指針 void * object_getIndexedIvars ( id obj ); // 返回對象中實例變量的值 id object_getIvar ( id obj, Ivar ivar ); // 設置對象中實例變量的值 void object_setIvar ( id obj, Ivar ivar, id value )
// 返回給定對象的類名 const char * object_getClassName ( id obj ); // 返回對象的類 Class object_getClass ( id obj ); // 設置對象的類 Class object_setClass ( id obj, Class cls );
// 獲取已注冊的類定義的列表
int objc_getClassList ( Class *buffer, int bufferCount );
// 創建並返回一個指向所有已注冊類的指針列表
Class * objc_copyClassList ( unsigned int *outCount );
// 返回指定類的類定義
Class objc_lookUpClass ( const char *name );
Class objc_getClass ( const char *name );
Class objc_getRequiredClass ( const char *name );
// 返回指定類的元類
Class objc_getMetaClass ( const char *name );