iOS runtime 之objc_msgsend(一)

381 阅读1分钟

什么是Runtime

它是由C、C++、汇编混合写成的,为OC提供运行时功能的一套API。

项目中runtime常见的用处

1.遍历属性,进行解档归档,字典转模型

2.交换方法

3.关联对象,给分类添加属性

4.消息转发,解决bug

objc_msgSend

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

clang后的结果

int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
    Person *p1 = ((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)p1,  sel_registerName("runTests"));
    ((void (*)(id, SEL))(void *)objc_msgSend)((id)p1, sel_registerName("runTests"));
    ((id)p1, sel_registerName("runTests"));
}
return 0;
}

可以清楚的发现,我们OC的方法调用转化成

((void (*)(id, SEL))(void *)objc_msgSend)((id)p1, sel_registerName("runTests"));

我们可以得出结论,方法的本质就是objc_segSend

接下来我们进行汇编分析 开启调试断点

Debug -> Debug Workflow -> Always Show Disassembly

 LGPerson *person = [[LGPerson alloc] init];;
 [person sayNB];

objc_msgSend源码分析

根据源码对应下面cooci整理的笔记分析