iOS app 加载流程
- 由 cpu 自硬盘中提取 app 数据流 加载至 内存中
- 链接app运行需要的各种库
- 执行文件,启动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
会产生一个很庞大当 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 的消息
那么,方法的本质由此证明就是 消息发送