OC类和对象之三
1,objc_getClass
1.1,简述
根据传入的class的name获取对应的Class结构,主要使用了look_up_class方法,它从一个hash结构中根据名字获取对应的Class结构,如果没有找到则返回NULL。
使用的主要方法有: look_up_class, NXHashGet
1.2,库代码
只需要关注objc_getclass, look_up_class, NSHashGet三个方法即可。
id objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName,NO, YES);
}
//根据类的名字查找对应class. old_class与Class结构体基本一致。
PRIVATE_EXTERN id look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler)
{
id result = nil;
struct old_class query;
query.name = aClassName;
if (!result && class_hash) {
// Check ordinary classes
mutex_lock (&classLock);
//通过NXHashGet方法获取对应的query
result = (id)NXHashGet(class_hash,&query);
mutex_unlock (&classLock);
}
return result;
}
2,objc_addClass
2.1,简述
将用户创建的class加入到系统的Hash结构中,加入的Class结构以后就可以使用objc_getClass获得到。虽然此方法已经被弃用了,但它描述了常规的加入Class的流程,因此简单说一下。重要方法有NXHashInsert, objc_addRegisteredClass是为了GC垃圾回收的,暂时不用考虑。
现在:
可以使用callingobjc_allocateClassPair创建一个Class. 然后通过 class_addMethodand class_addIvar.设置此Class的属性,通过调用objc_registerClassPair将Class加入到系统中,但是由于他们使用的结构体是新的class_t的结构,不是老的old_class的结构,而我在OC类和对象之一中是使用的old_class的结构,因此这里就采用old_class结构进行讲解了。新的和老的结构变化很大,主要的区别是class_t采用C++的一些方法,已经不是单纯的结构体,而是一个类;old_class还是一个纯粹的C结构体。
2.2,新旧结构描述
struct old_class {
struct old_class *isa;
struct old_class *super_class;
const char *name;
long version;
long info;
long instance_size;
struct old_ivar_list*ivars;
struct old_method_list**methodLists;
Cache cache;
structold_protocol_list *protocols;
// CLS_EXT only
const uint8_t *ivar_layout;
struct old_class_ext*ext;
};
虽然是类,但是是纯粹结构体描述
typedef struct class_t {
struct class_t *isa;
struct class_t *superclass;
Cache cache;
IMP *vtable;
uintptr_tdata_NEVER_USE; // class_rw_t * plus flags
class_rw_t *data() const {
#if CLASS_FAST_FLAGS_VIA_RW_DATA
return (class_rw_t*)(data_NEVER_USE & ~3UL);
#else
return (class_rw_t *)data_NEVER_USE;
#endif
}
void setData(class_rw_t *newData) {
#if CLASS_FAST_FLAGS_VIA_RW_DATA
uintptr_tflags = (uintptr_t)data_NEVER_USE & 3UL;
data_NEVER_USE = (uintptr_t)newData | flags;
#else
data_NEVER_USE = (uintptr_t)newData;
#endif
}
bool hasCustomRR() const {
#if CLASS_FAST_FLAGS_VIA_RW_DATA
return data_NEVER_USE& 1UL;
#else
return (data()->flags & RW_HAS_CUSTOM_RR);
#endif
}
voidsetHasCustomRR();
voidunsetHasCustomRR();
boolhasIvarReleaser() const {
return (data()->flags & RW_HAS_IVAR_RELEASER);
}
voidsetHasIvarReleaser();
bool isRootClass() const {
return superclass == NULL;
}
boolisRootMetaclass() const {
return isa == this;
}
} class_t;
有不少C++的函数,是纯粹的类。
2.3,库代码
/***********************************************************************
* objc_addClass. Add the specified class to the table of knownclasses,
* after doing a little verification and fixup.
**********************************************************************/
void objc_addClass (Class cls_gen)
{
struct old_class *cls =oldcls(cls_gen);
OBJC_WARN_DEPRECATED;
// Synchronize access to hash table
mutex_lock (&classLock);
// Make sure both the class and themetaclass have caches!
// Clear all bits of the info fields exceptCLS_CLASS and CLS_META.
// Normally these bits are already clearbut if someone tries to cons
// up their own class on the fly they mightneed to be cleared.
if (cls->cache == NULL) {
cls->cache = (Cache)&_objc_empty_cache;
cls->info = CLS_CLASS;
}
if (cls->isa->cache == NULL) {
cls->isa->cache = (Cache)&_objc_empty_cache;
cls->isa->info = CLS_META;
}
// methodLists should be:
// 1. NULL (Tiger and later only)
// 2. A -1 terminated method list array
// In either case, CLS_NO_METHOD_ARRAYremains clear.
// If the user manipulates the method listdirectly,
// they must use the magic private format.
// 就关注这一句,将cls加入到hash表中
(void) NXHashInsert (class_hash,cls);
objc_addRegisteredClass((Class)cls);
// Superclass is no longer a leaf for cacheflushing
if (cls->super_class &&(cls->super_class->info & CLS_LEAF)) {
_class_clearInfo((Class)cls->super_class, CLS_LEAF);
_class_clearInfo((Class)cls->super_class->isa,CLS_LEAF);
}
// Desynchronize
mutex_unlock (&classLock);
}
2.4,Hash
这里面的class的get和add主要就是一个hash的插入和获取,因此我就着重翻了一下hash结构的代码,内容还不少,不过由于大学的时候学过hash,就在这里抛砖引玉一下,希望大家给出更多的分析代码。具体内容且听下回分解hash。