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()