亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Objc源碼探究(五)category的加載

2019-11-06 09:52:55
字體:
來源:轉載
供稿:網友

本文擴展自:http://blog.sunnyxx.com/2014/08/30/objc-PRe-main/ 這篇文章主要描述了iOS平臺上main函數調用之前所發生的事。我們從這里開始講述category是如何加載的。

main函數開始之前,在一些準備工作之后,libSystem會調用

void _objc_init(void)

函數,這里便是runtime的入口,也就是這時候啟動了runtime。蘋果自己的注釋也描述的很清楚

/************************************************************* * _objc_init * Bootstrap initialization. Registers our image notifier with dyld. * Called by libSystem BEFORE library initialization time


蘋果在這個函數里面做了一些初始化的工作,包括每個類+load方法的調用,關于load方法的調用順序如下:

do { // 1. Repeatedly call class +loads until there aren't any more while (loadable_classes_used > 0) { call_class_loads(); } // 2. Call category +loads ONCE more_categories = call_category_loads(); // 3. Run more +loads if there are classes OR more untried categories } while (loadable_classes_used > 0 || more_categories);

接下來蘋果調用了map_2_images函數,函數里面在最后又調用了_read_images函數,該函數通過_objc_read_categories_from_image實現category的加載。該函數的實現如下:

static bool _objc_read_categories_from_image (header_info * hi){ Module mods; size_t midx; bool needFlush = NO; if (hi->info()->isReplacement()) { // Ignore any categories in this image return NO; } // Major loop - process all modules in the header mods = hi->mod_ptr; // NOTE: The module and category lists are traversed backwards // to preserve the pre-10.4 processing order. Changing the order // would have a small chance of introducing binary compatibility bugs. midx = hi->mod_count; while (midx-- > 0) { unsigned int index; unsigned int total; // Nothing to do for a module without a symbol table if (mods[midx].symtab == nil) continue; // Total entries in symbol table (class entries followed // by category entries) total = mods[midx].symtab->cls_def_cnt + mods[midx].symtab->cat_def_cnt; // Minor loop - register all categories from given module index = total; while (index-- > mods[midx].symtab->cls_def_cnt) { old_category *cat = (old_category *)mods[midx].symtab->defs[index]; needFlush |= _objc_register_category(cat, (int)mods[midx].version); } } return needFlush;}

首先判斷該類是否忽略加載category,如果忽略就直接返回;然后從傳入的hi(其中存儲的是各個加載的模塊的信息)參數中遍歷要加載的category的所有模塊;首先判斷模塊的符號表是否為空

// Nothing to do for a module without a symbol table if (mods[midx].symtab == nil) continue;

如果為空就不需要加載了;接下來從該模塊的符號表中取出category的數量和類的數量,然后遍歷該模塊所有的category,調用_objc_register_category函數進行加載。該函數的實現如下:

static bool _objc_register_category(old_category *cat, int version){ _objc_unresolved_category * new_cat; _objc_unresolved_category * old; Class theClass; // If the category's class exists, attach the category. if ((theClass = objc_lookUpClass(cat->class_name))) { return _objc_add_category_flush_caches(theClass, cat, version); } // If the category's class exists but is unconnected, // then attach the category to the class but don't bother // flushing any method caches (because they must be empty). // YES unconnected, NO class_handler if ((theClass = look_up_class(cat->class_name, YES, NO))) { _objc_add_category(theClass, cat, version); return NO; } // Category's class does not exist yet. // Save the category for later attachment. if (PrintConnecting) { _objc_inform("CONNECT: pending category '%s (%s)'", cat->class_name, cat->category_name); } // Create category lookup table if needed if (!category_hash) category_hash = NXCreateMapTable(NXStrValueMapPrototype, 128); // Locate an existing list of categories, if any, for the class. old = (_objc_unresolved_category *) NXMapGet (category_hash, cat->class_name); // Register the category to be fixed up later. // The category list is built backwards, and is reversed again // by resolve_categories_for_class(). new_cat = (_objc_unresolved_category *) malloc(sizeof(_objc_unresolved_category)); new_cat->next = old; new_cat->cat = cat; new_cat->version = version; (void) NXMapKeyCopyingInsert (category_hash, cat->class_name, new_cat); return NO;}

蘋果對該函數也進行了說明:

/************************************************************************ _objc_register_category.* Process a category read from an image. * If the category's class exists, attach the category immediately. * Classes that need cache flushing are marked but not flushed.* If the category's class does not exist yet, pend the category for * later attachment. Pending categories are attached in the order * they were discovered.* Returns YES if some method caches now need to be flushed.**********************************************************************/

如果category對應的類存在,那么就立即加載category;如果對應的類不存在,那么將category掛起等待后續加載;如果類的一些方法緩存需要刷新,但是刷新行為不在該函數中完成,該函數返回YES。 _objc_register_category函數首先去尋找category對應的類

// If the category's class exists, attach the category. if ((theClass = objc_lookUpClass(cat->class_name))) { return _objc_add_category_flush_caches(theClass, cat, version); } // If the category's class exists but is unconnected, // then attach the category to the class but don't bother // flushing any method caches (because they must be empty). // YES unconnected, NO class_handler if ((theClass = look_up_class(cat->class_name, YES, NO))) { _objc_add_category(theClass, cat, version); return NO; }

如果找到了,就加載category到對應的類,如果沒找到,就建立一個hash表,將這個category存起來,待之后系統去加載。 category的加載通過_objc_add_category_flush_caches函數實現:

/************************************************************************ _objc_add_category_flush_caches. Install the specified category's * methods into the class it augments, and flush the class' method cache.* Return YES if some method caches now need to be flushed.**********************************************************************/static bool _objc_add_category_flush_caches(Class cls, old_category *category, int version){ bool needFlush = NO; // Install the category's methods into its intended class { mutex_locker_t lock(methodListLock); _objc_add_category (cls, category, version); } // Queue for cache flushing so category's methods can get called if (category->instance_methods) { cls->setInfo(CLS_FLUSH_CACHE); needFlush = YES; } if (category->class_methods) { cls->ISA()->setInfo(CLS_FLUSH_CACHE); needFlush = YES; } return needFlush;}

這里面主要就是調用_objc_add_category函數,該函數的實現如下:

/************************************************************************ _objc_add_category. Install the specified category's methods and* protocols into the class it augments.* The class is assumed not to be in use yet: no locks are taken and * no method caches are flushed.**********************************************************************/static inline void _objc_add_category(Class cls, old_category *category, int version){ if (PrintConnecting) { _objc_inform("CONNECT: attaching category '%s (%s)'", cls->name, category->category_name); } // Augment instance methods if (category->instance_methods) _objc_insertMethods (cls, category->instance_methods, category); // Augment class methods if (category->class_methods) _objc_insertMethods (cls->ISA(), category->class_methods, category); // Augment protocols if ((version >= 5) && category->protocols) { if (cls->ISA()->version >= 5) { category->protocols->next = cls->protocols; cls->protocols = category->protocols; cls->ISA()->protocols = category->protocols; } else { _objc_inform ("unable to add protocols from category %s.../n", category->category_name); _objc_inform ("class `%s' must be recompiled/n", category->class_name); } } // Augment instance properties if (version >= 7 && category->instance_properties) { if (cls->ISA()->version >= 6) { _class_addProperties(cls, category->instance_properties); } else { _objc_inform ("unable to add instance properties from category %s.../n", category->category_name); _objc_inform ("class `%s' must be recompiled/n", category->class_name); } } // Augment class properties if (version >= 7 && category->hasClassPropertiesField() && category->class_properties) { if (cls->ISA()->version >= 6) { _class_addProperties(cls->ISA(), category->class_properties); } else { _objc_inform ("unable to add class properties from category %s.../n", category->category_name); _objc_inform ("class `%s' must be recompiled/n", category->class_name); } }}

這里主要是做了三件事: 1、將category的實例方法和類方法添加到類中 2、將category的protocol添加到類中 3、將category的實例對象和類對象添加到類中

至此,runtime幫助我們完成了所有的category的加載。

最后附上category的結構,其實也十分簡單:

struct old_category { char *category_name; char *class_name; struct old_method_list *instance_methods; struct old_method_list *class_methods; struct old_protocol_list *protocols; // Fields below this point are in version 7 or later only. uint32_t size; struct old_property_list *instance_properties; // Check size for fields below this point. struct old_property_list *class_properties; bool hasClassPropertiesField() const { return size >= offsetof(old_category, class_properties) + sizeof(class_properties); }};
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
伊人伊人伊人久久| 久久久伊人日本| 亚洲精品美女免费| 欧美一区二粉嫩精品国产一线天| 日韩av综合中文字幕| 亚洲免费影视第一页| 黑人巨大精品欧美一区二区免费| 韩日精品中文字幕| 国产一区二区三区日韩欧美| 性金发美女69hd大尺寸| 亚洲女人被黑人巨大进入| 91精品国产777在线观看| 久久偷看各类女兵18女厕嘘嘘| 亚洲精品视频免费| 国产精品吊钟奶在线| 成人97在线观看视频| 国产97在线亚洲| 久久亚洲精品网站| 91精品视频免费看| 久久视频在线视频| www.欧美精品| 欧美激情精品久久久久久黑人| 国产精品偷伦视频免费观看国产| 久久久噜噜噜久久| 国产精品com| 亚洲第一区中文99精品| 琪琪第一精品导航| 亚洲第一av在线| 高清欧美性猛交xxxx黑人猛交| 亚洲天堂av高清| 国产精品私拍pans大尺度在线| 国产日韩综合一区二区性色av| 亚洲最新中文字幕| 欧美在线视频观看免费网站| 精品久久久一区二区| 在线观看久久av| 2024亚洲男人天堂| 久久精品亚洲热| 日韩精品免费电影| 午夜精品久久久久久久99热| 4438全国亚洲精品在线观看视频| 国产精品久久77777| 亚洲天堂影视av| 久久69精品久久久久久国产越南| 国产精品v日韩精品| 日韩午夜在线视频| 国产精品美女呻吟| 久久精品电影网| 亚洲一二三在线| 日韩电影大全免费观看2023年上| 亚洲欧洲日产国产网站| 96国产粉嫩美女| 另类少妇人与禽zozz0性伦| 精品亚洲夜色av98在线观看| 91精品久久久久久久久久| 98精品在线视频| 蜜臀久久99精品久久久久久宅男| 亚洲精品大尺度| 日本精品视频网站| 欧美电影在线观看完整版| 精品亚洲男同gayvideo网站| 久久精品男人天堂| 蜜臀久久99精品久久久久久宅男| 91九色综合久久| 亚洲综合日韩中文字幕v在线| 国产精品视频26uuu| 欧美在线视频免费播放| 欧美日韩不卡合集视频| 国产97色在线|日韩| 伊人久久男人天堂| 精品国产精品自拍| 久久久99免费视频| 成人在线激情视频| 国产福利精品视频| 欧美精品videosex性欧美| www欧美xxxx| 国内精品小视频| 精品久久久久久中文字幕| 亚洲精品按摩视频| 亚洲欧洲美洲在线综合| 最近2019免费中文字幕视频三| 亚洲欧美国产va在线影院| 国产精品视频免费观看www| 精品国产乱码久久久久久婷婷| 国产精品久久999| 国产精品热视频| 久久久精品电影| 成人国产精品久久久久久亚洲| 亚洲综合日韩中文字幕v在线| 久久综合国产精品台湾中文娱乐网| 国产精品激情自拍| 日韩中文在线不卡| 亚洲欧美精品一区二区| 亚洲成人av在线播放| 亚洲国产第一页| zzijzzij亚洲日本成熟少妇| 欧美性20hd另类| 亚洲黄在线观看| 日韩美女在线播放| 久久久噜噜噜久久久| 久久久999国产精品| 欧美大人香蕉在线| 亚洲福利视频网站| 亚洲欧美激情精品一区二区| 国产日本欧美视频| 欧美性极品xxxx娇小| 日韩精品极品在线观看| 欧美黑人xxxx| 91色中文字幕| 日韩国产一区三区| 久久久极品av| 国产精品观看在线亚洲人成网| 国产精品第3页| 国产精品第三页| 国产精品美女网站| 国产精品欧美日韩一区二区| 欧美劲爆第一页| 欧美中文字幕在线播放| 91精品国产一区| 在线观看国产精品淫| 日韩高清人体午夜| 日韩欧美国产骚| 中文一区二区视频| 亚洲成人网在线观看| 久久久国产精品亚洲一区| 亚洲欧美综合区自拍另类| 久久久欧美一区二区| 欧美性感美女h网站在线观看免费| 蜜臀久久99精品久久久无需会员| 亚洲精品久久久久久下一站| 亚洲国产精品嫩草影院久久| 57pao成人永久免费视频| 日韩有码在线电影| 粉嫩老牛aⅴ一区二区三区| 国产日韩精品一区二区| 欧美日韩中国免费专区在线看| 国产精品视频专区| 欧美日韩视频免费播放| 成人性生交大片免费观看嘿嘿视频| 国产欧美在线播放| 精品亚洲精品福利线在观看| 久久久久久久久久亚洲| 亚洲一区二区久久久| 一本色道久久综合亚洲精品小说| 日韩av综合网| 日韩精品高清视频| 欧美性猛交xxxx乱大交| 国产精品免费看久久久香蕉| 欧美成人在线网站| 欧美大胆在线视频| 欧美性理论片在线观看片免费| 国产一区二区在线免费视频| 欧美老女人性生活| 夜夜嗨av一区二区三区免费区| 视频一区视频二区国产精品| 日韩精品视频免费专区在线播放| 欧美一级电影免费在线观看| 亚洲国产精品99久久| 亚洲欧洲偷拍精品| 国模精品一区二区三区色天香| 国产成人小视频在线观看| 狠狠色噜噜狠狠狠狠97| 91精品中国老女人| 欧美主播福利视频|