来看下代码实例html
@interface CFPerson : NSObject
{
NSString *body;
NSString *blood;
}
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *nickName;
复制代码
编译后底层代码结构markdown
extern "C" unsigned long OBJC_IVAR_$_CFPerson$_nickName;
extern "C" unsigned long OBJC_IVAR_$_CFPerson$_name;
struct CFPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *__strong body; NSObject *__strong blood;
NSString *__strong _nickName;
NSString *__strong _name;
};
复制代码
同时,属性编译会生成相应的objc_setProperty方法和当前的get方法app
static NSString * _I_CFPerson_nickName(CFPerson * self, SEL _cmd) { return (*(NSString *__strong *)((char *)self + OBJC_IVAR_$_CFPerson$_nickName)); }
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
static void _I_CFPerson_setNickName_(CFPerson * self, SEL _cmd, NSString *nickName) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct CFPerson, _nickName), (id)nickName, 0, 1); }
static NSString * _I_CFPerson_name(CFPerson * self, SEL _cmd) { return (*(NSString *__strong *)((char *)self + OBJC_IVAR_$_CFPerson$_name)); }
// 赋值
static void _I_CFPerson_setName_(CFPerson * self, SEL _cmd, NSString *name) { (*(NSString *__strong *)((char *)self + OBJC_IVAR_$_CFPerson$_name)) = name; }
// @end
复制代码
总结:{}里面的内容称为实例变量,实例变量便是特殊的成员变量【类的实例化】ide
属性便是带有下划线的成员变量+setter+getter方法函数
IMP:函数指针地址。好比一本书目录的页码oop
SEL: 方法编号。如一本书的目录名称源码分析
static struct /_method_list_t/ { unsigned int entsize; // sizeof(struct _objc_method) unsigned int method_count; struct _objc_method method_list[8]; } OBJC$_INSTANCE_METHODS_CFPerson attribute ((used, section ("__DATA,__objc_const"))) = { sizeof(_objc_method), 8, {{(struct objc_selector *)"nickName", "@16@0:8", (void *)_I_CFPerson_nickName}, {(struct objc_selector *)"setNickName:", "v24@0:8@16", (void *)I_CFPerson_setNickName}, {(struct objc_selector *)"name", "@16@0:8", (void *)_I_CFPerson_name}, {(struct objc_selector *)"setName:", "v24@0:8@16", (void *)I_CFPerson_setName}, {(struct objc_selector *)"nickName", "@16@0:8", (void *)_I_CFPerson_nickName}, {(struct objc_selector *)"setNickName:", "v24@0:8@16", (void *)I_CFPerson_setNickName}, {(struct objc_selector *)"name", "@16@0:8", (void *)_I_CFPerson_name}, {(struct objc_selector *)"setName:", "v24@0:8@16", (void *)I_CFPerson_setName}} };ui
static struct /_prop_list_t/ { unsigned int entsize; // sizeof(struct _prop_t) unsigned int count_of_properties; struct _prop_t prop_list[2]; } OBJC$_PROP_LIST_CFPerson attribute ((used, section ("__DATA,__objc_const"))) = { sizeof(_prop_t), 2, {{"nickName","T@"NSString",C,N,V_nickName"}, {"name","T@"NSString",&,N,V_name"}} };this
经过苹果官方各编码类型所指能够知道编码
/*
@16@0:8
@: 返回值
16 参数共用字节 16
第二个 @ :第一个参数 8
0 : 从0 开始
: : sel 8
*/
复制代码
咱们知道,在OC里面所谓的对象方法、实例方法,但在C/C++里却没有这一说。又OC在编译时底层必将趋于C/C++层,这个时候对象方法、实例方法就统称为方法。
代码举例
void cfObjc_copyMethodList(Class pClass){
unsigned int count = 0;
Method *methods = class_copyMethodList(pClass, &count);
for (unsigned int i=0; i < count; i++) {
Method const method = methods[i];
//获取方法名
NSString *key = NSStringFromSelector(method_getName(method));
LGLog(@"Method, name: %@", key);
}
free(methods);
}
void cfInstanceMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));
Method method3 = class_getInstanceMethod(pClass, @selector(sayHappy));
Method method4 = class_getInstanceMethod(metaClass, @selector(sayHappy));
LGLog(@"%s - %p-%p-%p-%p",__func__,method1,method2,method3,method4);
}
void cfClassMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getClassMethod(pClass, @selector(sayHello));//判断pClass方法里面是否有sayHello方法
Method method2 = class_getClassMethod(metaClass, @selector(sayHello));//判断元类metaClass方法里面是否有sayHello方法
Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
Method method4 = class_getClassMethod(metaClass, @selector(sayHappy));
LGLog(@"%s-%p-%p-%p-%p",__func__,method1,method2,method3,method4);
}
void lgIMP_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
// - (void)sayHello;
// + (void)sayHappy;
IMP imp1 = class_getMethodImplementation(pClass, @selector(sayHello));
IMP imp2 = class_getMethodImplementation(metaClass, @selector(sayHello));
IMP imp3 = class_getMethodImplementation(pClass, @selector(sayHappy));
IMP imp4 = class_getMethodImplementation(metaClass, @selector(sayHappy));
NSLog(@"%p-%p-%p-%p",imp1,imp2,imp3,imp4);
NSLog(@"%s",__func__);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
// 0x0000000100000000
// LGTeacher *teacher = [LGTeacher alloc];
CFPerson *person = [CFPerson alloc];
Class pClass = object_getClass(person);
lgObjc_copyMethodList(pClass);
cfInstanceMethod_classToMetaclass(pClass);
cfClassMethod_classToMetaclass(pClass);
NSLog(@"Hello, World!");
}
return 0;
}
复制代码
打印日志
打印结果能够看到
这两个方法并未查找到
Method method1 = class_getClassMethod(pClass, @selector(sayHello));
Method method2 = class_getClassMethod(metaClass, @selector(sayHello));
这两个方法能够查找到
Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
Method method4 = class_getClassMethod(metaClass, @selector(sayHappy));
在看下class_getClassMethod方法底层实现
Method class_getClassMethod(Class cls, SEL sel)
{
if (!cls || !sel) return nil;
return class_getInstanceMethod(cls->getMeta(), sel);
}
获得一个类的类方法就至关于获得一个元类的实例方法
复制代码
再往下走
static method_t *getMethod_nolock(Class cls, SEL sel)
{
method_t *m = nil;
runtimeLock.assertLocked();
// fixme nil cls?
// fixme nil sel?
ASSERT(cls->isRealized());
while (cls && ((m = getMethodNoSuper_nolock(cls, sel))) == nil) {
cls = cls->superclass;
}
return m;
}
若是是元类,则不会再递归下去,不然会一直循环
// NOT identical to this->ISA when this is a metaclass
Class getMeta() {
if (isMetaClass()) return (Class)this;
else return this->ISA();
}
复制代码
代码举例:
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; //
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; //
BOOL re3 = [(id)[CFPerson class] isKindOfClass:[CFPerson class]]; //
BOOL re4 = [(id)[CFPerson class] isMemberOfClass:[CFPerson class]]; //
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; //
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; //
BOOL re7 = [(id)[CFPerson alloc] isKindOfClass:[CFPerson class]]; //
BOOL re8 = [(id)[CFPerson alloc] isMemberOfClass:[CFPerson class]]; //
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
}
return 0;
}
复制代码
打印结果:
isKindOfClass和isMemberOfClass方法底层代码结构:
}
}
}
isKindOfClass方法内部先得到objc——getClass的类,而object_getClass的源码实现是去调用当前类的objc—>getIsa(),ISA()方法中得到元类meta class的指针,
接下来还有一个循环,先判断class是否等于meta class,不等则继续循环是否等于super class,不等再继续取super class,如此循环下去。
isMemberOfClass的源码实现是拿到本身的isa指针与本身取比较是否相等。