最近在研究無侵入的開屏廣告插入方式,受到眾多大神的啟示,利用NSObject的load方法。小白表示并不懂這個原理,上網(wǎng)查了資料,下來做一下整理。
1、NSObject
NSObject是絕大多是類的根類,它向其子類提供了基本的Runtime接口與objective-c Class的一些方法默認實現(xiàn),其中它在.h文件中提供了兩個方法
+ (void)load;
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
+ (void)initialize;
Initializes the class before it receives its first message.
這兩個方法由Runtime動態(tài)調(diào)用(Runtime懂吧,個人理解的意思就是OC在運行時動態(tài)的幫我們完成某些動作,推薦一篇文章http://www.itdecent.cn/p/927c8384855a)
2、+ (void)load;
一、此方法調(diào)用時機很早,運行環(huán)境有不確定因素。具體點來說就是當Runtime將類加載時被調(diào)用,而且這個時機要先于appdelegate中的didFinishLaunchingWithOptions。
二、假如在一個庫中多個文件同時重寫+(void)load;,那么它的調(diào)用順序是不固定的,這就照應了上一條,運行環(huán)境的不確定因素。但是假如兩個類有依賴關(guān)系或者繼承關(guān)系,被依賴者和被繼承者+(void)load;會先調(diào)用,程序開發(fā)的時候需要考慮到這一點。
三、+(void)load;是不必寫明[super load]的,父類就會接收到調(diào)用。
四、Category的load也會收到調(diào)用,但順序上在主類的load調(diào)用之后。
五、只會被調(diào)用一次。
3、+ (void)initialize;
一、蘋果官方是這么描述的:該方法會在第一次初始化這個類之前被調(diào)用
二、initialize會在類接受第一個消息的線程中被調(diào)用。
三、initialize里的代碼不應該過于復雜,因為initialize會阻塞class的message sending。
四、當subclass沒有實現(xiàn)initialize方法的時候或者直接調(diào)用[super initialize]時,initialize會被重復調(diào)用。
為了防止initialize多次調(diào)用,可以在initialize方法中加入判斷當前調(diào)用者是否為當前類本身
+(void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
總結(jié)
上面廢話太多了總結(jié)來說就是你在類里重寫了+load方法,他就會被調(diào)用,而且是在didFinishLaunchingWithOptions之前。
比如文章開頭的無侵入廣告技術(shù)就是利用這點。
但+ initialize方法類似懶調(diào)用,就是只有你使用了該類才會調(diào)用該方法,調(diào)用在init之前。注意這兩個方法默認只會調(diào)用一次,但假如有子類,父類的initialize方法會被重復調(diào)用。load就絕不會出現(xiàn)多次調(diào)用的情況。