iOS main()執行前的過程 + weak 置 nil的過程

weixin_33895657發表於2018-05-30

main()

    1. MachO 初始化;
    1. 讀取程式碼檔案(ImageLoader);
    1. dyld 通知 runtime 對 map_images 進行處理;
    1. + load 方法;
    1. dyld 呼叫 main 函式.

ps: 第一次啟動 app 耗時較長, 就是由於要將 MachO 載入到快取中, 等到第二次啟動 app 時, 直接從快取中讀取資料!

weak

runtime 會對註冊的類進行佈局, 物件被 weak 修飾以後, 將呼叫 objc_initWeak 初始化一個新的 weak 指標指向物件地址, 然後呼叫 objc_storeWeak() 更新新的指標的指向, 建立弱引用 hash 表(將物件地址作為 key, 將 weak 指標地址作為 value), 最後等到引用計數為0時, 呼叫 clearDeallocating 將hash 表中 key 所對應的 valueArray 全部置 nil, 然後清除此條記錄.

  • 置 nil 的步驟:
      1. 呼叫 objc_release();
      1. dealloc();
      1. _objc_rootDealloc();
      1. object_dispose();
      1. objc_destructInstance();
      1. objc_clear_deallocating

runloop

runloop 是一個讓執行緒能隨時處理事件但不退出的機制. runloop 實際是一個物件, 這個物件管理了其需要處理的事件和訊息, 並提供了一個入口函式來執行 Event Loop 邏輯. 執行緒執行了這個函式後, 就會一直處於這個函式內部 "接受訊息"->"等待"->"處理"的迴圈中, 直到這個迴圈結束(quit).
iOS/OSX 系統中, 提供了兩個 runloop 物件, NSRunloop 和 CFRunloopRef. 執行緒和 runloop 之間是一一對應的, 其關係是儲存在一個全域性的字典中. 執行緒建立時並沒有開啟 runloop, 如果不主動獲取, 那它一直不會開啟. runloop 的建立是發生在第一次獲取時, runloop 的銷燬是發生線上程結束時. 只能現線上程內部, 獲取當前執行緒的 runloop(主執行緒除外).

相關文章