運行時相關

1、objc中向一個nil對象發送消息會發生什麼?

不起作用,但不會奔潰

原因:objc是動態語言,每個方法在運行時會被動態轉爲消息發送,即objc_msgSend(receiver,selector)

 

objc_class的源碼定義

// runtime.h(類在runtime中的定義)
// http://weibo.com/luohanchenyilong/
// https://github.com/ChenYilong

struct objc_class {
  Class isa OBJC_ISA_AVAILABILITY; //isa指針指向Meta Class,因爲Objc的類的本身也是一個Object,爲了處理這個關係,runtime就創造了Meta Class,當給類發送[NSObject alloc]這樣消息時,實際上是把這個消息發給了Class Object
  #if !__OBJC2__
  Class super_class OBJC2_UNAVAILABLE; // 父類
  const char *name OBJC2_UNAVAILABLE; // 類名
  long version OBJC2_UNAVAILABLE; // 類的版本信息,默認爲0
  long info OBJC2_UNAVAILABLE; // 類信息,供運行期使用的一些位標識
  long instance_size OBJC2_UNAVAILABLE; // 該類的實例變量大小
  struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 該類的成員變量鏈表
  struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定義的鏈表
  struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法緩存,對象接到一個消息會根據isa指針查找消息對象,這時會在method Lists中遍歷,如果cache了,常用的方法調用時就能夠提高調用的效率。
  struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 協議鏈表
  #endif
  } OBJC2_UNAVAILABLE;

objc在向一個對象發送消息時,runtime庫會根據對象的isa指針找到該方法實際所屬類(metaClass),然後在該類中的方法列表以及其父類的方法列表中尋找方法執行。

 

2、什麼時候會報unrecognized selector的異常?

當調用該對象上某個方法,而該對象上沒有實現這個方法的時候,可以通過“消息轉發”進行解決。

 

3、一個objc對象的isa指向?有什麼作用?

指向他的類對象,從而找到對象上的方法

 

4、OC中的self 和super

self是類的隱藏參數,指向當前調用方法的這個類的實例

super和self是指向同一個消息接受者,只是super會告訴編譯器,調用方法時,要去父類的方法裏找、而不是本類。

所有爲什麼不推薦在init方法中使用點語法,而應該使用_ivar,因爲子類有可能覆寫setter

 

當調用[self class]  ->  id objc_msgSend(id self, SEL op, ...)

當調用[super class] ->  會轉換成id objc_msgSendSuper(struct objc_super *super, SEL op, ...)

第一個參數是 objc_super 這樣一個結構體,其定義如下:

struct objc_super {
      __unsafe_unretained id receiver;
      __unsafe_unretained Class super_class;
};

調用[super class] 整個過程

  • 會轉換成id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
  • 構造 objc_super 結構體,結構體第一個成員就是 self 、 第二個成員是 (id)class_getSuperclass(objc_getClass(“Son”)) , 實際該函數輸出結果爲 Father。
  • 去 Father這個類裏去找 - (Class)class,發現沒有,去NSObject類去找,找到了。
  • 使用 objc_msgSend(objc_super->receiver, @selector(class))去調用

 

5、使用runtime Association方法關聯的對象需要在主對象dealloc的時候釋放嗎?

不需要,因爲NSObject的dealloc幫你做了。

對象的內存銷燬時間表,分成四個步驟

1、調用 -release: 引用計數變爲0

  •       對象正在被銷燬,生命週期即將結束
  •       不能再用新的_weak 弱引用,否則將指向nil
  •       調用[self dealloc]

2、子類調用 -dealloc

      繼承關係中的每一層的父類,都調用-dealloc

3、NSObject調用 -dealloc

     調用OC runtime中的object_dispose方法

4、調用object_dispose

  •       爲C++的實例變量(iVars) 調用destructors
  •       爲ARC狀態下的實例變量們調用-release
  •       解除所有使用runtime Associate 方法關聯的對象
  •       解除所有_weak引用
  •       調用free()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章