前言html
@interface XDPerson : NSObject
{
NSString *nickName; //成员变量
// UILabel *label; //实例变量 是特殊的成员变量 经过类实例出来的
}
@property (nonatomic,copy) NSString *name; //属性
@end
@implementation XDPerson
@end
复制代码
咱们准备一份这样的代码放在
main.m
文件里面,经过clang -rewrite-objc main.m -o main.cpp
来编译成mian.cpp
文件。bash
main.cpp
文件咱们直接看与XDPerson
相关的代码app
struct NSObject_IMPL {
Class isa;
};
···
#ifndef _REWRITER_typedef_XDPerson
#define _REWRITER_typedef_XDPerson
typedef struct objc_object XDPerson;
typedef struct {} _objc_exc_XDPerson;
#endif
extern "C" unsigned long OBJC_IVAR_$_XDPerson$_name;
struct XDPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *nickName;
NSString *_name;
};
// @property (nonatomic,copy) NSString *name;
/* @end */
// @implementation XDPerson
static NSString * _I_XDPerson_name(XDPerson * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_XDPerson$_name)); }
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
static void _I_XDPerson_setName_(XDPerson * self, SEL _cmd, NSString *name) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct XDPerson, _name), (id)name, 0, 1); }
// @end
复制代码
XDPerson
这个类在底层编译成了XDPerson_IMP
结构体。- 成员
NSObjct_IVARS
,这是一个结构体,里面只包含了isa
。- 成员
nickName
,是咱们类里面的成员变量。- 成员
_name
,是咱们类里面的属性,编译成了带有_
下划线的成员。- 函数
_I_XDPerson_name
,实际上就是getter
方法,包含两个默认参数self
、_cmd
。- 函数
_I_XDPerson_setName_
,实际上就是setter
方法,包含两个默认参数self
、_cmd
,与一个形参name
。
根据编译的结构咱们能够得出下面结论:iphone
成员变量
+getter方法
+setter方法
组成。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_XDPerson __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
2,
{{(struct objc_selector *)"name", "@16@0:8", (void *)_I_XDPerson_name},
{(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_XDPerson_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函数实现
组成。ide
type方法签名
介绍咱们拿v24@0:8@16
分析:函数
v
返回值类型,24
返回值类型的长度。@
参数一类型对象
,0
长度0-7
。:
参数二类型SEL
,8
长度8-15
。@
参数三类型对象
,16
长度16-23
。这里咱们能够经过打印一下各类类型来获取各类符号typeEncode
:post
NSLog(@"char--%s",@encode(char));
NSLog(@"short--%s",@encode(short));
NSLog(@"int--%s",@encode(int));
NSLog(@"long--%s",@encode(long));
NSLog(@"long long--%s",@encode(long long));
NSLog(@"unsigned char--%s",@encode(unsigned char));
NSLog(@"unsigned short--%s",@encode(unsigned short));
NSLog(@"unsigned int--%s",@encode(unsigned int));
NSLog(@"unsigned long--%s",@encode(unsigned long));
NSLog(@"float--%s",@encode(float));
NSLog(@"BOOL--%s",@encode(BOOL));
NSLog(@"void--%s",@encode(void));
NSLog(@"char *--%s",@encode(char *));
NSLog(@"id--%s",@encode(id));
NSLog(@"Class--%s",@encode(Class));
NSLog(@"SEL--%s",@encode(SEL));
int array[] = {1,2};
NSLog(@"int[]--%s",@encode(typeof(array)));
typedef struct person{
int age;
NSString *name;
}Person;
NSLog(@"struct--%s",@encode(Person));
typedef union teacher{
char *a;
BOOL b;
}Teacher;
NSLog(@"union--%s",@encode(Teacher));
2019-12-19 20:47:51.143558+0800 Object本质[2623:63103] char--c
2019-12-19 20:47:51.143887+0800 Object本质[2623:63103] short--s
2019-12-19 20:47:51.143906+0800 Object本质[2623:63103] int--i
2019-12-19 20:47:51.143966+0800 Object本质[2623:63103] long--q
2019-12-19 20:47:51.144035+0800 Object本质[2623:63103] long long--q
2019-12-19 20:47:51.144080+0800 Object本质[2623:63103] unsigned char--C
2019-12-19 20:47:51.144108+0800 Object本质[2623:63103] unsigned short--S
2019-12-19 20:47:51.144131+0800 Object本质[2623:63103] unsigned int--I
2019-12-19 20:47:51.144153+0800 Object本质[2623:63103] unsigned long--Q
2019-12-19 20:47:51.144173+0800 Object本质[2623:63103] float--f
2019-12-19 20:47:51.144193+0800 Object本质[2623:63103] BOOL--c
2019-12-19 20:47:51.144213+0800 Object本质[2623:63103] void--v
2019-12-19 20:47:51.144234+0800 Object本质[2623:63103] char *--*
2019-12-19 20:47:51.144256+0800 Object本质[2623:63103] id--@
2019-12-19 20:47:51.144277+0800 Object本质[2623:63103] Class--#
2019-12-19 20:47:51.144297+0800 Object本质[2623:63103] SEL--:
2019-12-19 20:47:51.144317+0800 Object本质[2623:63103] int[]--[2i]
2019-12-19 20:47:51.144337+0800 Object本质[2623:63103] struct--{person=i@}
2019-12-19 20:47:51.144359+0800 Object本质[2623:63103] union--(teacher=*c)
复制代码
咱们能够直接经过苹果官网TypeEncode或者在Xcode中在@Encode
用commond+shift+0
来查看。ui
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
@end
复制代码
clang
编译文件这里若是还用上面的方式来编译,应该是会报错的,须要用下面的方式atom
ViewController.cpp
文件#ifndef _REWRITER_typedef_ViewController
#define _REWRITER_typedef_ViewController
typedef struct objc_object ViewController;
typedef struct {} _objc_exc_ViewController;
#endif
struct ViewController_IMPL {
struct UIViewController_IMPL UIViewController_IVARS;
};
/* @end */
// @interface ViewController ()
/* @end */
// @implementation ViewController
static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) {
((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad"));
}
struct UIViewController_IMPL {
struct UIResponder_IMPL UIResponder_IVARS;
};
// @end
复制代码
- 类
ViewController
在底层也被编译成告终构体。惟一成员是继承自父类的成员。viewDidLoad
方法在底层编译成_I_ViewController_viewDidLoad
函数,默认也是两个参数self
、_cmd
。super viewDidLoad
方法在底层编译成((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad"));
,这个函数简化以后objc_msgSendSuper(self.super,viewDidLoad)
,其本质就是给父类发送viewDidLoad
这么一个消息。
method_list_t
结构体查看static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[1];
} _OBJC_$_INSTANCE_METHODS_ViewController __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
1,
{{(struct objc_selector *)"viewDidLoad", "v16@0:8", (void *)_I_ViewController_viewDidLoad}}
};
复制代码
能够看到一样也
SEL->selector
+typeEncode
+imp
组成。spa
XDPerson *p1 = [XDPerson alloc];
XDPerson *p2 = [XDPerson alloc];
XDPerson *p3 = [XDPerson alloc];
NSLog(@"p1-%p",p1);
NSLog(@"p2-%p",p2);
NSLog(@"p3-%p",p3);
2019-12-19 21:42:33.901531+0800 alloc探索[3108:105948] p1-0x600000639da0
2019-12-19 21:42:33.901750+0800 alloc探索[3108:105948] p2-0x60000063ae20
2019-12-19 21:42:33.901878+0800 alloc探索[3108:105948] p3-0x600000639620
复制代码
经过输出结果能够看到对象
alloc
一次在系统内存中就会增长一份。
Class c1 = [XDPerson class];
Class c2 = [XDPerson alloc].class;
Class c3 = object_getClass([XDPerson alloc]);
NSLog(@"c1-%p",c1);
NSLog(@"c2-%p",c2);
NSLog(@"c3-%p",c3);
2019-12-19 21:42:33.901996+0800 alloc探索[3108:105948] c1-0x10b8f30e8
2019-12-19 21:42:33.902107+0800 alloc探索[3108:105948] c2-0x10b8f30e8
2019-12-19 21:42:33.902205+0800 alloc探索[3108:105948] c3-0x10b8f30e8
复制代码
经过输出结果能够看到类的数量在系统内存中只有一份。