iOS底层原理之—dyld与objc的关联

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在"},{"type":"codeinline","content":[{"type":"text","text":"dyld"}]},{"type":"text","text":"加载过程中,我们知道会调用"},{"type":"codeinline","content":[{"type":"text","text":"_objc_init"}]},{"type":"text","text":"方法,那么在"},{"type":"codeinline","content":[{"type":"text","text":"_objc_init"}]},{"type":"text","text":"方法中究竟做了什么呢?我们来探究下。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"_objc_init方法"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"_objc_init方法实现"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"void _objc_init(void)\n{\n static bool initialized = false;\n if (initialized) return;\n initialized = true;\n\n // fixme defer initialization until an objc-using image is found?\n environ_init();\n tls_init();\n static_init();\n runtime_init();\n exception_init();\n cache_init();\n _imp_implementationWithBlock_init();\n\n _dyld_objc_notify_register(&map_images, load_images, unmap_image);\n\n#if __OBJC2__\n didCallDyldNotifyRegister = true;\n#endif\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从"},{"type":"codeinline","content":[{"type":"text","text":"_objc_init"}]},{"type":"text","text":"实现中我们分析下该方法主要做了什么"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"environ_init()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"该方法主要是读取运行时的环境变量,我们可以通过设置"},{"type":"codeinline","content":[{"type":"text","text":"DYLD_PRINT_STATISTICS = YES"}]},{"type":"text","text":"来打印APP启动到main()函数之前的时长,进而可以进行APP启动优化。具体的environ_init()简介可参考博客"},{"type":"link","attrs":{"href":"https://www.jianshu.com/p/25bcb6540045","title":null},"content":[{"type":"text","text":"iOS-底层原理 16:dyld与objc的关联"}]},{"type":"text","text":"中有关"},{"type":"codeinline","content":[{"type":"text","text":"nviron_init()"}]},{"type":"text","text":"部分的介绍"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"tls_init()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要用于关于线程key的绑定,比如每线程数据的析构函数。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"void tls_init(void)\n{\n#if SUPPORT_DIRECT_THREAD_KEYS\n pthread_key_init_np(TLS_DIRECT_KEY, &_objc_pthread_destroyspecific);\n#else\n _objc_pthread_key = tls_create(&_objc_pthread_destroyspecific);\n#endif\n}\n"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"static_init()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要是C++静态构造函数"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"static void static_init()\n{\n size_t count;\n auto inits = getLibobjcInitializers(&_mh_dylib_header, &count);\n for (size_t i = 0; i < count; i++) {\n inits[i]();\n }\n}\n"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"runtime_init()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要是运行时的初始化,主要分为两部分:"},{"type":"codeinline","content":[{"type":"text","text":"分类初始化"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"类的表初始化"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"void runtime_init(void)\n{\n objc::unattachedCategories.init(32);\n objc::allocatedClasses.init();\n}\n复制代码\n"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"exception_init()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"初始化libobjc异常处理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"/***********************************************************************\n* exception_init\n* Initialize libobjc's exception handling system.\n* Called by map_images().\n**********************************************************************/\nvoid exception_init(void)\n{\n old_terminate = std::set_terminate(&_objc_terminate);\n}\n"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"cache_init()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要是缓存初始化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"void cache_init()\n{\n#if HAVE_TASK_RESTARTABLE_RANGES\n mach_msg_type_number_t count = 0;\n kern_return_t kr;\n\n while (objc_restartableRanges[count].location) {\n count++;\n }\n\n kr = task_restartable_ranges_register(mach_task_self(),\n objc_restartableRanges, count);\n if (kr == KERN_SUCCESS) return;\n _objc_fatal(\"task_restartable_ranges_register failed (result 0x%x: %s)\",\n kr, mach_error_string(kr));\n#endif // HAVE_TASK_RESTARTABLE_RANGES\n}\n"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"_imp_implementationWithBlock_init()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要用来启动机制回调"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"/// everything is initialized lazily, but for certain processes we eagerly load\n/// the trampolines dylib.\nvoid\n_imp_implementationWithBlock_init(void)\n{\n#if TARGET_OS_OSX\n // Eagerly load libobjc-trampolines.dylib in certain processes. Some\n // programs (most notably QtWebEngineProcess used by older versions of\n // embedded Chromium) enable a highly restrictive sandbox profile which\n // blocks access to that dylib. If anything calls\n // imp_implementationWithBlock (as AppKit has started doing) then we'll\n // crash trying to load it. Loading it here sets it up before the sandbox\n // profile is enabled and blocks it.\n //\n // This fixes EA Origin (rdar://problem/50813789)\n // and Steam (rdar://problem/55286131)\n if (__progname &&\n (strcmp(__progname, \"QtWebEngineProcess\") == 0 ||\n strcmp(__progname, \"Steam Helper\") == 0)) {\n Trampolines.Initialize();\n }\n#endif\n}\n"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"dyld与objc关联"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"_dyld_objc_notify_register(&map_images, load_images, unmap_image)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要是"},{"type":"codeinline","content":[{"type":"text","text":"dyld"}]},{"type":"text","text":"注册 实际代码实现"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped,\n _dyld_objc_notify_init init,\n _dyld_objc_notify_unmapped unmapped)\n{\n dyld::registerObjCNotifiers(mapped, init, unmapped);\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上文正中我们可以看出"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"mapped"}]},{"type":"text","text":"即"},{"type":"codeinline","content":[{"type":"text","text":"map_images"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"init"}]},{"type":"text","text":"即"},{"type":"codeinline","content":[{"type":"text","text":"load_images"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"unmapped"}]},{"type":"text","text":"即"},{"type":"codeinline","content":[{"type":"text","text":"unmap_image"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"map_images()函数分析"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"/***********************************************************************\n* map_images\n* Process the given images which are being mapped in by dyld.\n* Calls ABI-agnostic code after taking ABI-specific locks.\n*\n* Locking: write-locks runtimeLock\n**********************************************************************/\nvoid\nmap_images(unsigned count, const char * const paths[],\n const struct mach_header * const mhdrs[])\n{\n mutex_locker_t lock(runtimeLock);\n return map_images_nolock(count, paths, mhdrs);\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从"},{"type":"codeinline","content":[{"type":"text","text":"map_images"}]},{"type":"text","text":"函数中我们发现"},{"type":"codeinline","content":[{"type":"text","text":"map_images_nolock函数"}]},{"type":"text","text":"是重点,我们进入"},{"type":"codeinline","content":[{"type":"text","text":"map_images_nolock"}]},{"type":"text","text":"函数"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"map_images_nolock"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们查看代码实现"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/20/203fc78b41fdc4cdb300eb6ac6f9022b.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从截图中我们可以看出"},{"type":"codeinline","content":[{"type":"text","text":"_read_images"}]},{"type":"text","text":"是我们要重点研究的方法"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"_read_images函数分析"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"是否是第一次加载"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3b/3bb412bea75aa6b491ec57a9ba936b92.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"修复预编译时"},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"@selector"}]},{"type":"text","text":"的错乱问题"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9d/9daf187e4a92ac44184a0bc1c2361b33.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"错误类处理,通过"},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"readClass"}]},{"type":"text","text":"读取出来类的信息"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/39/39bd3cd13cdfdbdf5a66b5021d3e312f.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"重新设置映射镜像"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d2/d2b751c9c12e14022aea377e8dd4b434.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"消息处理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b5/b51413d0898e5f64b0b757d62c19450b.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"类中如果有协议,读取协议"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/dc/dcd7d9a5ee77e49779e21dd3e4efe3a5.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"映射协议"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0b/0bcb82e36377c586e5a5d527fe2d3ce5.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"加载分类"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/66/668cfae9fba3de8ccae6b4375cb4ca04.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"注意"}]},{"type":"text","text":"在分类处理中主要是通过"},{"type":"codeinline","content":[{"type":"text","text":"load_categories_nolock"}]},{"type":"text","text":"处理,我们进入"},{"type":"codeinline","content":[{"type":"text","text":"load_categories_nolock"}]},{"type":"text","text":"函数中"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"load_categories_nolock"}]},{"type":"text","text":"函数"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"static void load_categories_nolock(header_info *hi) {\n bool hasClassProperties = hi->info()->hasCategoryClassProperties();\n\n size_t count;\n auto processCatlist = [&](category_t * const *catlist) {\n for (unsigned i = 0; i < count; i++) {\n category_t *cat = catlist[i];\n Class cls = remapClass(cat->cls);\n locstamped_category_t lc{cat, hi};\n\n if (!cls) {\n // Category's target class is missing (probably weak-linked).\n // Ignore the category.\n if (PrintConnecting) {\n _objc_inform(\"CLASS: IGNORING category \\?\\?\\?(%s) %p with \"\n \"missing weak-linked target class\",\n cat->name, cat);\n }\n continue;\n }\n\n // Process this category.\n if (cls->isStubClass()) {\n // Stub classes are never realized. Stub classes\n // don't know their metaclass until they're\n // initialized, so we have to add categories with\n // class methods or properties to the stub itself.\n // methodizeClass() will find them and add them to\n // the metaclass as appropriate.\n if (cat->instanceMethods ||\n cat->protocols ||\n cat->instanceProperties ||\n cat->classMethods ||\n cat->protocols ||\n (hasClassProperties && cat->_classProperties))\n {\n objc::unattachedCategories.addForClass(lc, cls);\n }\n } else {\n // First, register the category with its target class.\n // Then, rebuild the class's method lists (etc) if\n // the class is realized.\n if (cat->instanceMethods || cat->protocols\n || cat->instanceProperties)\n {\n if (cls->isRealized()) {\n attachCategories(cls, &lc, 1, ATTACH_EXISTING);\n } else {\n objc::unattachedCategories.addForClass(lc, cls);\n }\n }\n\n if (cat->classMethods || cat->protocols\n || (hasClassProperties && cat->_classProperties))\n {\n if (cls->ISA()->isRealized()) {\n attachCategories(cls->ISA(), &lc, 1, ATTACH_EXISTING | ATTACH_METACLASS);\n } else {\n objc::unattachedCategories.addForClass(lc, cls->ISA());\n }\n }\n }\n }\n };\n\n processCatlist(_getObjc2CategoryList(hi, &count));\n processCatlist(_getObjc2CategoryList2(hi, &count));\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从"},{"type":"codeinline","content":[{"type":"text","text":"load_categories_nolock"}]},{"type":"text","text":"函数实现中,我们可以看到该函数将"},{"type":"codeinline","content":[{"type":"text","text":"类"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"实例方法"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"协议"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"属性"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"类方法"}]},{"type":"text","text":"等再次链接了一次。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"非懒加载类处理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/17/17d174908c921fe744b4c53aac5e5de0.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"处理没有使用的类"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/34/34489fdb93dfa6ab0a4052595f7cf929.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"dyld与objc关联总结"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"dyld_start"}]},{"type":"text","text":"调用"},{"type":"codeinline","content":[{"type":"text","text":"_objc_init"}]},{"type":"text","text":"来初始化,"},{"type":"codeinline","content":[{"type":"text","text":"_objc_init"}]},{"type":"text","text":"中通过"},{"type":"codeinline","content":[{"type":"text","text":"dyld"}]},{"type":"text","text":"调用"},{"type":"codeinline","content":[{"type":"text","text":"_dyld_objc_notify_register"}]},{"type":"text","text":"函数,传入"},{"type":"codeinline","content":[{"type":"text","text":"map_images"}]},{"type":"text","text":"跟"},{"type":"codeinline","content":[{"type":"text","text":"load_images"}]},{"type":"text","text":"这两个参数来处理"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"map_images"}]},{"type":"text","text":"通过"},{"type":"codeinline","content":[{"type":"text","text":"map_images_nolock"}]},{"type":"text","text":"函数调用"},{"type":"codeinline","content":[{"type":"text","text":"_read_images"}]},{"type":"text","text":"函数"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在"},{"type":"codeinline","content":[{"type":"text","text":"_read_images"}]},{"type":"text","text":"函数中处理"},{"type":"codeinline","content":[{"type":"text","text":"类信息、属性、协议、分类等"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"当一切准备妥当,则再次返回"},{"type":"codeinline","content":[{"type":"text","text":"dyld_start"}]},{"type":"text","text":"中,此时"},{"type":"codeinline","content":[{"type":"text","text":"dyld"}]},{"type":"text","text":"跟"},{"type":"codeinline","content":[{"type":"text","text":"objc"}]},{"type":"text","text":"关联了起来"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"资料推荐"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群"},{"type":"link","attrs":{"href":"https://links.jianshu.com/go?to=https%3A%2F%2Fjq.qq.com%2F%3F_wv%3D1027%26k%3D5JFjujE","title":null},"content":[{"type":"text","text":"1012951431"}]},{"type":"text","text":"来获取一份详细的大厂面试资料为你的跳槽多添一份保障。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/92/92394154a3e96888899d492b73de1e69.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章