日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

+load +initialize

發布時間:2023/11/27 生活经验 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 +load +initialize 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

+load方法

在app啟動的時候各個類的+load方法都會被調用+load方法不是通過消息機制調用的,它是直接調用的,因此無論是在子類或者category中復寫此方法,復寫的+load方法都會被調用,查看runtime的代碼可知調用的順序為

父類->子類->分類。(原因是runtime會把所有類的+load方法放到一個列表中,然后按順序調用,所有category的+load方法放到一個列表中,然后也按順序調用,所以當所有類的+load方法都執行完成后才開始去執行分類的+load方法)。所有類的+load方法在調用列表中的順序由兩個因素決定,一個是此類文件的編譯順序,一個是遞歸調用的順序,即從父類到子類。所有分類的+load方法在調用列表中的順序只由編譯順序決定

?

schedule_class_load

call_class_load

?

runtime代碼如下:

static void schedule_class_load(Class cls)

{

? ? if (!cls) return;

? ? assert(cls->isRealized());? // _read_images should realize

?

? ? if (cls->data()->flags & RW_LOADED) return;

?

? ? // Ensure superclass-first ordering

? ? schedule_class_load(cls->superclass);

?

? ? add_class_to_loadable_list(cls);

? ? cls->setInfo(RW_LOADED);?

}

?

?

prepare_load_methods

call_load_methods

?

void call_load_methods(void)

{

? ? static bool loading = NO;

? ? bool more_categories;

?

? ? loadMethodLock.assertLocked();

?

? ? // Re-entrant calls do nothing; the outermost call will finish the job.

? ? if (loading) return;

? ? loading = YES;

?

? ? void *pool = objc_autoreleasePoolPush();

?

? ? 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);

?

? ? objc_autoreleasePoolPop(pool);

?

? ? loading = NO;

}

?

?

+initialize

與+load方法不同+initialize方法是通過消息的方式發送的(msgSend),所以+initialize方法可以被子類或者分類覆蓋每個類第一次被用到的時候,runtime都會調用 _class_initialize(Class cls)方法,_class_initialize(Class cls)也是一個遞歸調用的方法,當發現cls的父類沒有調用此方法時,會遞歸調用_class_initialize(cls->supercls),調用時會向該類發送initialize消息,此方法被調用完成后cls->isInitialized()這個屬性會變成true

注意這里存在一個類的initialize方法被調用多次的可能當子類沒有實現initialize方法時,父類的initialize方法可能被調用多次

舉個例子:

有兩個類:Person,Girl,Girl繼承Person

如果只有Person實現了initialize方法,那么當這Girl類被用到時,Person的這個initialize方法會被調用兩次,一次是父類調用_class_initializePerson時發送的,另一次是調用_class_initializeGirl)時發送的,因為給Girl發送initialize的時候發現Girl并沒有實現此方法,所以此方法被轉發到了Girl的父類,即Person的類對象。

?

可以這么理解,每個類對應的_class_initialize(Class cls)這個方法只會被調用一次,調用的順序為從父類到子類,在_class_initialize(Class cls)這個方法中會向當前的類對象發送initialize方法。如果當前類沒有實現initialize方法則依次去父類找

?

_class_initialize(Class cls)

?

void _class_initialize(Class cls)

{

? ? assert(!cls->isMetaClass());

?

? ? Class supercls;

? ? BOOL reallyInitialize = NO;

?

? ? // Make sure super is done initializing BEFORE beginning to initialize cls.

? ? // See note about deadlock above.

? ? supercls = cls->superclass;

? ? if (supercls? &&? !supercls->isInitialized()) {

? ? ? ? _class_initialize(supercls);

? ? }

?? ?

? ? // Try to atomically set CLS_INITIALIZING.

? ? {

? ? ? ? monitor_locker_t lock(classInitLock);

? ? ? ? if (!cls->isInitialized() && !cls->isInitializing()) {

? ? ? ? ? ? cls->setInitializing();

? ? ? ? ? ? reallyInitialize = YES;

? ? ? ? }

? ? }

?? ?

? ? if (reallyInitialize) {

? ? ? ? // We successfully set the CLS_INITIALIZING bit. Initialize the class.

?? ? ? ?

? ? ? ? // Record that we're initializing this class so we can message it.

? ? ? ? _setThisThreadIsInitializingClass(cls);

?? ? ? ?

? ? ? ? // Send the +initialize message.

? ? ? ? // Note that +initialize is sent to the superclass (again) if?

? ? ? ? // this class doesn't implement +initialize. 2157218

? ? ? ? if (PrintInitializing) {

? ? ? ? ? ? _objc_inform("INITIALIZE: calling +[%s initialize]",

?? ? ? ? ? ? ? ? ? ? ? ? cls->nameForLogging());

? ? ? ? }

?

? ? ? ? ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);

?

? ? ? ? if (PrintInitializing) {

? ? ? ? ? ? _objc_inform("INITIALIZE: finished +[%s initialize]",

?? ? ? ? ? ? ? ? ? ? ? ? cls->nameForLogging());

? ? ? ? } ? ? ? ?

?? ? ? ?

? ? ? ? // Done initializing.?

? ? ? ? // If the superclass is also done initializing, then update?

? ? ? ? // ? the info bits and notify waiting threads.

? ? ? ? // If not, update them later. (This can happen if this +initialize?

? ? ? ? // ? was itself triggered from inside a superclass +initialize.)

? ? ? ? monitor_locker_t lock(classInitLock);

? ? ? ? if (!supercls? ||? supercls->isInitialized()) {

? ? ? ? ? ? _finishInitializing(cls, supercls);

? ? ? ? } else {

? ? ? ? ? ? _finishInitializingAfter(cls, supercls);

? ? ? ? }

? ? ? ? return;

? ? }

?? ?

? ? else if (cls->isInitializing()) {

? ? ? ? // We couldn't set INITIALIZING because INITIALIZING was already set.

? ? ? ? // If this thread set it earlier, continue normally.

? ? ? ? // If some other thread set it, block until initialize is done.

? ? ? ? // It's ok if INITIALIZING changes to INITIALIZED while we're here,?

? ? ? ? // ? because we safely check for INITIALIZED inside the lock?

? ? ? ? // ? before blocking.

? ? ? ? if (_thisThreadIsInitializingClass(cls)) {

? ? ? ? ? ? return;

? ? ? ? } else {

? ? ? ? ? ? monitor_locker_t lock(classInitLock);

? ? ? ? ? ? while (!cls->isInitialized()) {

? ? ? ? ? ? ? ? classInitLock.wait();

? ? ? ? ? ? }

? ? ? ? ? ? return;

? ? ? ? }

? ? }

?? ?

? ? else if (cls->isInitialized()) {

? ? ? ? // Set CLS_INITIALIZING failed because someone else already?

? ? ? ? // ? initialized the class. Continue normally.

? ? ? ? // NOTE this check must come AFTER the ISINITIALIZING case.

? ? ? ? // Otherwise: Another thread is initializing this class. ISINITIALIZED?

? ? ? ? // ? is false. Skip this clause. Then the other thread finishes?

? ? ? ? // ? initialization and sets INITIALIZING=no and INITIALIZED=yes.?

? ? ? ? // ? Skip the ISINITIALIZING clause. Die horribly.

? ? ? ? return;

? ? }

?? ?

? ? else {

? ? ? ? // We shouldn't be here.?

? ? ? ? _objc_fatal("thread-safe class init in objc runtime is buggy!");

? ? }

}

?

轉載于:https://www.cnblogs.com/yibinpan/p/9693184.html

總結

以上是生活随笔為你收集整理的+load +initialize的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。