_attribute__表示屬性,是Clang提供的一種源碼註釋,方便開發者向編譯器表達訴求,通常以__attribute__(*)的方式出如今代碼中。爲了方便使用,一些經常使用屬性被定義成了宏,常常出如今系統頭文件中。好比NS_CLASS_AVAILABLE_IOS(9_0) 就是 __attribute__(availability(9.0)) 這個屬性的簡單寫法。下面介紹一些可能會頻繁使用到的屬性
函數
這個屬性表示一個類不能夠被繼承。若是咱們但願咱們寫的某個類不被繼承,那麼只須要在@interface前面加上這個屬性便可,這樣若是有類繼承了此類,在編譯的時候就會報錯ui
__attribute__((objc_subclassing_restricted))spa
@interface NoSon : NSObject.net
@endrest
這個屬性表示子類繼承這個方法時必需要調用super方法,不然編譯器會給出警告。宏寫法是NS_REQUIRES_SUPERcode
@interface MustCallSuper : NSObject繼承
-(void)testMethod __attribute__((objc_requires_super));開發
-(void)testMethod1 NS_REQUIRES_SUPER;get
@end編譯器
Objective-C最後仍是轉譯成C語言,固然還有constructor / destructor
加上這兩個屬性的函數會在分別在可執行文件(或 shared library)load 和 unload 時被調用,能夠理解爲在 main()
函數調用前和 return 後執行
實際上constructor會在+load
以後執行
由於 dyld(動態連接器)最開始會先通知 objc runtime 去加載其中全部的類,每加載一個類時,它的 +load 隨之調用,所有加載完成後,dyld 纔會調用全部的 constructor 方法
CaptainHook 也是利用這一原理來實現的,這樣作有幾個優勢:
+load
同樣 寫在一個 Class 裏面__attribute__((constructor))
static void beforeMain(void) {
printf("%s","beforeMain");
}
__attribute__((destructor))
static void afterMain(void) {
printf("%s","afterMain");
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
return 0;
}
如有多個 constructor 且想控制優先級的話,能夠寫成 attribute((constructor(101))),裏面的數字越小優先級越高,1 ~ 100 爲系統保留。