美文网首页
Runtime初探---类和方法的本质

Runtime初探---类和方法的本质

作者: wlysky | 来源:发表于2019-07-08 16:03 被阅读0次

iOS app 加载流程

  1. 由 cpu 自硬盘中提取 app 数据流 加载至 内存中
  2. 链接app运行需要的各种库
  3. 执行文件,启动app
    具体加载流程可参考下面这篇文章
    iOS APP启动性能优化

object-c 相关本质的探索

在日常开发中,对象,我们平时常用,那么对象的本质是什么呢?

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN
@interface Person : NSObject

- (void)run;

@end
NS_ASSUME_NONNULL_END


#import "Person.h"
@implementation Person

@end

#import <Foundation/Foundation.h>
#include <objc/runtime.h> 
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc]init];
        [p run];
    }
    return 0;
}

如上,创建一个简单当app,含有一个 Person 类 ,在.m中并没有实现该方法。当我们编译当时候并不会报错,在app启动后 会崩溃 ,这是为什么呢?

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o testmain.c++
在项目文件夹中使用如上命令,来clang 一下 main.m


clang 后文件

会产生一个很庞大当 c++文件,上面部分都是在引入相关资源文件,可以先不用看,来到最后面,我们会发现 在第 33249 行 有一个person IMP的结构体,由此可见,对象的本质是 结构体。我们继续往下看,这里是main函数的入口,代码中

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc]init];
        [p run];
    }
    return 0;

main函数我们只是创建了一个 Person 对象 这里

        Person * p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init"));
        ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("run"));
    }

很长的一段代码,我们去掉各种类型转换

      Person * p = (id, SEL)objc_msgSend(objc_msgSend)((objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init"));

      (objc_msgSend)(p, sel_registerName("run"));
    }

最后可以理解为:
Person 对象接受了一个 alloc 的方法 获取到一个对象之后 该对象接受了一个 init 的方法 最后获取到的对象赋值给了 p 然后 p 对象接受了一个 run 的消息
那么,方法的本质由此证明就是 消息发送

相关文章

网友评论

      本文标题:Runtime初探---类和方法的本质

      本文链接:https://www.haomeiwen.com/subject/pyoohctx.html