-
iOS的開發(fā)語言objective-c,它的真實面目是它不是真正的面向?qū)ο笳Z言,而抽象理解為此而已。其實它就是C+坤次,有個公式可以很好地詮釋那就是
OC = C + Runtime;
接下來我們就好好講講在Runtime下的objc-class古劲。
一斥赋、Class定義
1.1 小小說明一下objc-api.h里的OBJC_ISA_AVAILABILITY:
/*介紹一下attribute((deprecated))的作用,__attribute是給函數(shù)、變量产艾、類做屬性說明的關(guān)鍵字疤剑,deprecated是棄用原先的進(jìn)行兼容
若是OBJC2,原先的類滑绒,編譯器發(fā)出警告*/
#if !defined(OBJC_ISA_AVAILABILITY)
# if __OBJC2__
# define OBJC_ISA_AVAILABILITY __attribute__((deprecated))
# else
# define OBJC_ISA_AVAILABILITY /* still available */
# endif
#endif
typedef struct objc_method *Method;
typedef struct objc_ivar *Ivar;
typedef struct objc_category *Category;
typedef struct objc_property *objc_property_t;
1.2 接下來就是runtime.h里的Class的定義:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;//每個Class都有一個isa指針
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;//父類
const char *name OBJC2_UNAVAILABLE;//類名
long version OBJC2_UNAVAILABLE;//類版本
long info OBJC2_UNAVAILABLE;//!*!供運行期使用的一些位標(biāo)識。如:CLS_CLASS (0x1L)表示該類為普通class; CLS_META(0x2L)表示該類為metaclass等(runtime.h中有詳細(xì)列出)
long instance_size OBJC2_UNAVAILABLE;//實例大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;//存儲每個實例變量的內(nèi)存地址
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;//!*!根據(jù)info的信息確定是類還是實例隘膘,運行什么函數(shù)方法等
struct objc_cache *cache OBJC2_UNAVAILABLE;//緩存
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;//協(xié)議
#endif
} OBJC2_UNAVAILABLE;
二疑故、class初始化
- Runtime的行為之一就是initialize。在程序運行過程中弯菊,它會在你程序中每個類調(diào)用一次initialize纵势。這個調(diào)用的時間發(fā)生在你的類接收到消息之前,但是在它的超類接收到initialize之后管钳。
//在蘋果的官方Runtime中有個objc-initialize.m文件钦铁,進(jìn)行解讀
typedef struct _objc_initializing_classes {
int classesAllocated;//類是否分配存在
Class *metaclasses;//類的父類,如果沒有父類那就是自身
} _objc_initializing_classes;//初始化一個對象_objc_initializing_classes
//將所有的類存儲在靜態(tài)鏈表中,以待接下來的接收和發(fā)送消息
static _objc_initializing_classes *_fetchInitializingClassList(BOOL create)
{
_objc_pthread_data *data;
//list為類鏈表
_objc_initializing_classes *list;
Class *classes;
data = _objc_fetch_pthread_data(create);
if (data == nil) return nil;
//鏈表增加類節(jié)點
list = data->initializingClasses;
if (list == nil) {
if (!create) {
return nil;
} else {
list = (_objc_initializing_classes *)
_calloc_internal(1, sizeof(_objc_initializing_classes));
data->initializingClasses = list;
}
}
//將創(chuàng)建的classes接在metaclasses后
classes = list->metaclasses;
if (classes == nil) {
// If _objc_initializing_classes exists, allocate metaclass array,
// even if create == NO.
// Allow 4 simultaneous class inits on this thread before realloc.
list->classesAllocated = 4;
classes = (Class *)
_calloc_internal(list->classesAllocated, sizeof(Class));
list->metaclasses = classes;
}
return list;
}
3才漆、runtime下Class的各項操作(重要幾個)
3.1 add*(增加)
3.1.1 static IMP addMethod(Class cls, SEL name, IMP imp, const char *types, BOOL replace);//增加方法
3.1.2 BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);//增加類方法
3.1.3 BOOL class_addIvar(Class cls, const char *name, size_t size,uint8_t alignment, const char *type);//增加實例變量
3.1.4 static BOOL _class_addProperty(Class cls, const char *name,const objc_property_attribute_t *attrs, unsigned int count,BOOL replace);//增加屬性
3.2 replace*(修改)
3.2.1 IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types); //修改方法
3.2.2 void class_replaceProperty(Class cls, const char *name,const objc_property_attribute_t *attrs, unsigned int n);//修改屬性
3.3 get*(獲取)
3.3.1 static Class getClass(const char *name);//獲取類
3.3.2 static ivar_t *getIvar(Class cls, const char *name);//獲取類變量(static相當(dāng)于“+“)
3.3.3 Method class_getInstanceMethod(Class cls, SEL sel);//獲取實例方法
3.3.4 static Method _class_getMethod(Class cls, SEL sel);;//獲取類方法
3.3.5 static Protocol *getProtocol(const char *name);//增加協(xié)議
3.4 set*(設(shè)置)
3.4.1 objc_class::setInitialized();//set的initialized初始化
3.4.2 static Class setSuperclass(Class cls, Class newSuper);//設(shè)置父類
3.5 其他還有類似于 void *objc_destructInstance(id obj);//摧毀實例對象等等
四牛曹、Class的重要函數(shù)
4.1 get*(獲取)
4.1.1 object_getClass(id obj);
4.1.2 IMP object_getMethodImplementation(id obj, SEL name);//獲得實例方法實現(xiàn)
4.1.3 Ivar object_getInstanceVariable(id obj, const char *name, void **value)//獲取實例屬性
4.2 set*(設(shè)置)
4.2.1 Class object_setClass(id obj, Class cls);
4.2.2 Ivar object_setInstanceVariable(id obj, const char *name, void *value);//設(shè)置實例屬性
4.2.3 void object_setIvar(id obj, Ivar ivar, id value);//設(shè)置實例變量
4.3 其他
4.3.1 static void _class_resolveClassMethod(Class cls, SEL sel, id inst);//動態(tài)添加類方法,不必在乎方法是否存在
4.3.2 static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst);//動態(tài)添加實現(xiàn)方法醇滥,不必在乎方法是否存在
4.3.3 unsigned _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone,id *results, unsigned num_requested);//創(chuàng)建實例存儲空間
4.4 消息轉(zhuǎn)發(fā)
4.4.1 void instrumentObjcMessageSends(BOOL flag);//flag傳入YES黎比,運行時發(fā)送的所有消息都會打印到/tmp/msgSend-xxxx文件里了。