1、retain和strong
他倆都是強引用,除了某些情況下不一樣,其他的時候也是可以通用的。
在修飾block屬性的時候,相信大家都知道要用copy吧,因為如果不copy的話,block是存放在棧連里面的,他的生命周期會隨著函數的結束而出棧的,copy之后會放在堆里面。
strong在修飾block的時候就相當于copy,而retain修飾block的時候就相當于assign,這樣block會出現提前被釋放掉的危險。
2、能否向編譯后得到的類中增加實例變量?能否向運行時創建的類中添加實例變量?為什么?
不能向編譯后得到的類中增加實例變量;
能向運行時創建的類中添加實例變量;
因為編譯后的類已經注冊在 runtime 中,類結構體中的objc_ivar_list實例變量的鏈表 和instance_size實例變量的內存大小已經確定,同時runtime 會調用class_setIvarLayout或class_setWeakIvarLayout來處理 strong weak 引用。所以不能向存在的類中添加實例變量;
運行時創建的類是可以添加實例變量,調用class_addIvar函數。但是得在調用objc_allocateClassPair(創建類)之后,objc_registerClassPair(注冊類)之前,原因同上。
當你觀察一個對象時,一個新的類會被動態創建。這個類繼承自該對象的原本的類,并重寫了被觀察屬性的 setter 方法。重寫的 setter 方法會負責在調用原 setter 方法之前和之后,通知所有觀察對象:值的更改。最后通過isa 混寫(isa-swizzling)把這個對象的 isa 指針 ( isa 指針告訴 Runtime 系統這個對象的類是什么 ) 指向這個新創建的子類,對象就神奇的變成了新創建的子類的實例
鍵值觀察通知依賴于 NSObject 的兩個方法:willChangeValueForKey:和didChangevlueForKey:。在一個被觀察屬性發生改變之前,willChangeValueForKey:一定會被調用,這就會記錄舊的值。而當改變發生后,observeValueForKey:ofObject:change:context:會被調用,繼而didChangeValueForKey:也會被調用
4、load方法與initialize方法區別
load方法在這個文件被程序裝載時調用,load方法總是在main函數之前調用。如果一個類沒有實現load方法,那么就不會調用它父類的load方法。
5、runtime 中,SEL 和 IMP 的區別
SEL : 類成員方法的指針,但不同于C語言中的函數指針,函數指針直接保存了方法的地址,但SEL只是方法編號。
IMP:一個函數指針,保存了方法的地址