相关文章
iOS开发-底层原理总结 - 关联对象实现原理
iOS开发-底层原理 - KVO
[]
1.方法底层调用
首先写一个简单Demo
#import <Foundation/Foundation.h>
#import "XZPerson.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
XZPerson *p = [XZPerson alloc];
[p sayHappy];
}
return 0;
}
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface XZPerson : NSObject
-(void)sayHappy;
@end
NS_ASSUME_NONNULL_END
#import "XZPerson.h"
@implementation XZPerson
-(void)sayHappy{
NSLog(@"say happy")
}
@end
可以看出,很简单,只是在main函数中调用了一个XZPerson类中的一个方法,下面我们通过clang,对main文件进行编译;使用终端进入main文件目录:clang -rewrite-objc main.m -o main1.cpp ,同级目录下生成编译后cpp文件 直接查看main函数
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
XZPerson *p = ((XZPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("XZPerson"), sel_registerName("alloc"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("sayHappy"));
}
return 0;
}
我们将类型强转去掉方便我们对代码进行分析
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
XZPerson *p = (objc_msgSend)(objc_getClass("XZPerson")
,sel_registerName("alloc"));
(objc_msgSend)(p, sel_registerName("sayHappy"));
}
return 0;
}
这样我们就可以很清晰的看出来,方法的本质,其实就是底层通过objc_msgSend方法进行发送消息其中有2个参数
- 参数一:消息接收者
- 参数二:sel类型的方法编号
这里的方法编号sel 就可以联系到上篇文章中的cache中,通过sel在找到imp 并在cache中进行方法查找,并进行返回
我们在main中写一个C语言的方法
#import <Foundation/Foundation.h>
#import "XZPerson.h"
void run(){
NSLog(@"%s",__func__);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
XZPerson *p = [XZPerson alloc];
[p sayHappy];
run();
}
return 0;
}
再次进行clang :这次输出main2.m文件,编译完成后查看源码
void run(){
NSLog((NSString *)&__NSConstantStringImpl__var_folders_vl_y9rmzqq165ngxyd_yz2dmz0h0000gn_T_main_784d77_mi_0,__func__);
}
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
XZPerson *p = ((XZPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("XZPerson"), sel_registerName("alloc"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("sayHappy"));
run();
}
return 0;
}
我们可以看到C语言方法,直接进行调用,而我们的OC方法需要使用objc_msgSend方法进行查找方法进行调用,这就说明
objc_msgSeng 方法其实就是OC方法进行查找底层实现的方法实现的过程并进行调用,而C语言函数实现可以直接找到C语言函数名就是函数指针直接找到地址进行调用;
原文链接:iOS底层探索八(方法本质上)
网友评论