对象的本质
1.在main.m中准备代码如下
@interface LGPerson : NSObject{
NSString *name; // 成员变量 : 底层编译不会生成相应的 setter getter
// lgTeacher *t; // 实例变量 : 是一种特殊的成员变量 (类声明而来 实例 - id (void *))
}
@property (nonatomic, copy) NSString *name; // 属性的区别
@end
@implementation LGPerson
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"123");
}
return 0;
}
通过clang -rewrite-objc main.m -o main.cpp 编译底层源码命令来编译成mian.cpp文件。
2.分析编译生成的main.cpp文件,直接看与LGPerson相关的内容
#ifndef _REWRITER_typedef_LGPerson
#define _REWRITER_typedef_LGPerson
typedef struct objc_object LGPerson;
typedef struct {} _objc_exc_LGPerson;
#endif
extern "C" unsigned long OBJC_IVAR_$_LGPerson$_name;
struct LGPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *name;
NSString *_name;
};
// @property (nonatomic, copy) NSString *name;
/* @end */
// @implementation LGPerson
static NSString * _I_LGPerson_name(LGPerson * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_name)); }
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
static void _I_LGPerson_setName_(LGPerson * self, SEL _cmd, NSString *name) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct LGPerson, _name), (id)name, 0, 1); }
// @end
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_jh_7w1wkg8j5w58pf3sv2s3pzvr0000gn_T_main_e4cb5b_mi_0);
}
return 0;
}
可以看出在底层生成了一个结构体,对象的本质就是结构体
struct LGPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *name;
NSString _name;
};
成员 NSObject_IMPL 只包含一个isa,
struct NSObject_IMPL {
Class isa;
};
成员name,是我们类里面的成员变量。
成员name,是我们类里面的属性,编译成了带有下划线的成员。
static NSString * _I_LGPerson_name(LGPerson * self, SEL _cmd) { return ((NSString **)((char *)self + OBJC_IVAR__name)); },
这个函数实际上就是getter方法,包含两个默认参数self、_cmd。
static void I_LGPerson_setName(LGPerson * self, SEL _cmd, NSString *name) { objc_setProperty (self, _cmd, OFFSETOFIVAR(struct LGPerson, _name), (id)name, 0, 1); }
函数I_LGPerson_setName,实际上就是setter方法,包含两个默认参数self、cmd,与一个形参name。
从上可以看出成员变量与属性的区别,属性会用修饰,而且会有setter和getter方法
3.析method_list_t结构体
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[2];
} _OBJC_$_INSTANCE_METHODS_LGPerson __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
2,
{{(struct objc_selector *)"name", "@16@0:8", (void *)_I_LGPerson_name},
{(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_LGPerson_setName_}}
};
我们分析一下这两个objc_selector
{{(struct objc_selector *)"name", "@16@0:8", (void *)_I_XDPerson_name},
{(struct objc_selector *)"setName:", "v24@0:8@16", (void *)I_XDPerson_setName}}
两个都是由SEL->selector,type方法签名,imp函数实现组成。与上面的setter和getter方法对应
type方法签名介绍:
我们拿v24@0:8@16分析:
第一个符号v返回值类型,24返回值类型的长度。
第二个符号@参数一类型对象,0长度0-7。
第三个符号:参数二类型SEL,8长度8-15。
第四个符号@参数三类型对象,16长度16-23。
我们可以直接通过苹果官网TypeEncode或者在Xcode中在@Encode
用commond+shift+0
来查看。