废话少说,直接上干货。
1、首先用X-code创建一个工程选择->macOS->Command Line Tool->填写工程名称oc -info。
2、创建完成后会有一个main.m文件,在文件内看到如下代码:
#import <Foundation/Foundation.h>
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
}
return 0;
}
3、我们在这个main.m创建一个Person类。并且在main中初始化Person、给属性赋值、调用方法。代码如下:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy)NSString *name;
- (void)showMyInfo;
@end
@implementation Person
- (void)showMyInfo{
NSLog(@"showMyInfo");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [Person alloc];
p = [p init];
p.name = @"zhang san";
[p showMyInfo];
}
return 0;
}
Person初始化分为两部,是为了后面通过clang 来查看每个步骤调用的具体实现。
首先我们利用终端cd 到当前main.m文件同目录下。然后执行下面clang 语句
clang -rewrite-objc main.m
该命令可以将.m的OC文件转写为.cpp文件。
在工程目录下找到main.cpp文件并打开。会看到如下代码片段:
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc"));
p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("init"));
((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)p, sel_registerName("setName:"), (NSString *)&__NSConstantStringImpl__var_folders_pc_kltvgylx09l_qc2x15njv2wh0000gp_T_main_08433e_mi_1);
((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("showMyInfo"));
}
return 0;
}
初始化Person当调用alloc 方法时候转化c语言代码
Person *p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"));
这一行代码做了三件事情,第一获取Person
类,第二注册alloc
方法,第三发送消息,将消息alloc
发送给类对象,可以简单的将注册方法理解为,通过方法名获取到转写后C语言函数的函数指针。
当调用init 方法时代码如下
p = objc_msgSend(p, sel_registerName("init"));
注册了init
方法,然后通过objc_msgSend
函数将消息init
发送给消息的接受者p
。
//这一行是用来查找参数的地址,取名为name
(NSString *)&__NSConstantStringImpl__var_folders_pc_kltvgylx09l_qc2x15njv2wh0000gp_T_main_08433e_mi_1
objc_msgSend(p, sel_registerName("setName:"), name)
和上面类似,注册一个setName:方法、传递一个参数。再利用objc_msgSend 发送给消息接受者p.
调用方法和上面方式一样如下:
objc_msgSend(p, sel_registerName("showMyInfo"));
可以看出OC的runtime
通过objc_msgSend
函数将一个面向对象的消息传递转为了面向过程的函数调用。