[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f_6VWJvDq-LZ3948XWznNksBvm4a57PpCQzHn0kOhXY8":3},{"code":4,"message":5,"data":6},200,"成功",{"id":7,"createdAt":8,"title":9,"content":10,"summary":11,"image":12,"uid":13,"user":14,"categoryId":21,"category":22,"subCategoryId":24,"subCategory":25,"comments":27,"status":17,"reason":12,"notice":12,"visitCount":28,"commentCount":29,"keywords":30},34,"2024-01-29T15:10:42.462Z","Runtime底层原理分析","官方：\\\nurl: \u003Chttps://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008048>\n\n# OC对象、方法\n1.  OC对象的本质是结构体；\n2.  方法的本质是消息发送；\n3.  消息的组成：\n```main.m\nPerson *p = [[Person alloc] init];\n[p run];\n```\n本质：\n```main.mm\nPerson *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass(\"Person\"), sel_registerName(\"new\"));\n((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName(\"run\"))\n```\n\n*   消息接收者：p\n*   方法：`sel_registerName(\"run\")` -> 方法编号 -- 字符串name \\\n    通过sel 找到函数实现的指针.\\\n    函数实现类似于：\n```\nvoid runIMP(id self, SEL _cmd) {\n    ...\n}\n```\n\n# Runtime调用的3种方式\n1.  runtime api\n2.  NSObject api isKindOf, isMemberOf\n3.  编译器提供的oc上层方法 @selector\n4.  向父类发消息\n\n- 对象方法:\n```\nstruct objc_super mySuper;\nmySuper.receiver = s;\nmySuper.super_class = class_getSuperclass([s class]);\nobjc_msgSendSuper(&mySuper, @selector(run));\n```\n\n- 类方法:\n```\nstruct objc_super myClassSuper;\nmyClassSuper.receiver = [s class];\nmyClassSuper.super_class = class_getSuperclass(object_getClass([s class));  // 元类\nobjc_msgSendSuper(&myClassSuper, sel_registerName(\"walk\"));\n```\n*   类方法存在元类之中，以实例方法的姿态形式存在\n*   对象在类中是一个实例，类在元类中也是一个实例\n\n# objc_msgSend\n1. 快速\n- 缓存找 汇编 -> cache_t 找imp通过hash表\n- cache在类结构体中\n\n2. 慢速\n直接通过C, C++, 汇编来找. 找到后存缓存\n*   [x] objc\\_msgSend用汇编来写\n*   [x] 如果用C函数，不能写一个函数，跳转到任意的指针\n*   [x] C还要往下层编译，汇编快\n*   [x] 汇编有寄存器, x0 - x31\n\n# 源码分析\n`tagged pointer`特殊的数据类型\n1.  \\_objc\\_msgSend\n2.  LNilOrTagged\n3.  LGetIsaDone isa处理完毕\n4.  CacheLoopup NORMAL\n\n*   call imp\n\n*   objc\\_msgSend\\_uncached\n\n*   CacheHit\n\n*   CheckMiss -> \\_objc\\_msgSend\\_uncached\n\n*   add\n\nadditional: bl汇编指令就是跳转.\n\nMethodTableLookup\n\n## C、C++:\n1.  lookUpImpOrForward\n2.  relizeClass(cls)\n3.  \\_class\\_initialize\n4.  漫长的过程 -> 找方法 -> 找自己 -> 找父类 -> NSObject\n\n*   getMethodNoSuper\\_nolock 递归查找方法列表中的方法\n\n*   log\\_and\\_fill\\_cache\n\n*   [x] remap(cls)重映射\n\n1.  resolver动态解析 \\\n    如果方法没有实现，走resolver方法. \\\n    动态解析一次. \\\n    流程：\n\n*   lookup imp\n*   如果没有，走\\_class\\_resolveMethod（只走一次）\n*   如果不是元类，走\\_class\\_resolveInstanceMethod\n*   如果是元类，走\\_class\\_resolveClassMethod，再\\_class\\_resolveInstanceMethod\n\n1.  消息转发forwardingTargetForSelector\n2.  方法签名\n3.  无法处理doesNotRecognize\n\n\n## 查看所有的objc_msgSend信息的函数\n```\nextern void instrumentobjcMessageSends(BOOL);\n```\n可以在private -> tmp -> msgSends-进程号\n\n### 总结\n\nruntime就是可以做到\n\n1.  动态添加注册类\n2.  查询/添加属性、方法\n3.  等\n","iOS的runtime的底层概念和调用方式。","",499668042977349,{"phone":15,"userId":13,"nickName":16,"vipType":17,"avatar":18,"sign":19,"createdAt":20},"13121171998","全栈老韩",1,"https://image.xinwei.ltd/images/IMG_5430.JPG","全栈工程师，擅长iOS App开发、前端（vue、react、nuxt、小程序&Taro）开发、Flutter、React Native、后端（midwayjs、golang、express、koa）开发、docker容器、seo优化等。","2024-01-01T16:14:30.305Z",2,{"id":21,"name":23},"IT技术",3,{"id":24,"name":26,"parentId":21},"iOS",[],87,0,"ios,ios开发,ios runtime"]