iOS Runtime筆記,iosruntime筆記
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 );// 類執行個體是否響應指定的selectorBOOL 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 );