iOS __attribute__
最近在逛博客的過程中看到__attribute__的例子,就整理了一下,自己動手嘗試了幾個比較常用的。
對于__attribute__網上是這么解釋的:
Clang Attributes是Clang提供的一種源碼注解,方便開發(fā)者向編譯器表達某種要求,參與控制如Static Analyzer、Name Mangling、Code Generation等過程,一般以attribute(xxx)的形式出現在代碼中;為方便使用,一些常用屬性也被Cocoa定義成宏,比如在系統頭文件中經常出現的NS_CLASS_AVAILABLE_IOS(9_0)就是attribute(availability(...))這個屬性的簡單寫法。
下面來看例子
1 __attribute__((objc_subclassing_restricted))
restricted是受限制的意思,表示這個類不能被繼承,它修飾在一個類的頭文件中
我寫了一個類表示狗,一個表示貓,繼承的時候就會報錯
2?__attribute__((objc_requires_super))
這個修飾在方法之后,表示子類重寫這個方法須調用父類的方法,否則會給警告,我們用小狗來演示
我們可以看到調用super后警告就會消失
3__attribute__((objc_runtime_name("wolf")))
這個表示可以修改一個類的isa指針,用于?@interface?或?@protocol,將類或協議的名字在編譯時指定成另一個,代碼混淆用它再好不過了
我們對ClangAttributeCat類做了標記,可以看到在運行時類的名字做了改變
4?__attribute__((deprecated("str")))
方法警告提示,修飾在方法或屬性的后面,在調用的時候會給出警告提示,str是我們警告的內容
例子很簡單不多說
5?NS_UNAVAILABLE
禁止使用標識,也是修士在屬性和方法的后面,標識禁止使用。
NS_UNAVAILABLE是一個宏定義,點擊進入后可以看見
#define NS_UNAVAILABLE UNAVAILABLE_ATTRIBUTE
UNAVAILABLE_ATTRIBUTE也是一個宏定義,我們可以直接使用兩個作用是一樣的,進入宏定義后我們又會發(fā)現
#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
最終還是用的__attribute__((unavailable)),所以例子也很簡單,unavailable后面可以加提示。
6?__attribute__((constructor))/__attribute__((destructor))
構造解析器,修飾的方法可以再main方法前后分別運行,注意的是constructor 和?+load?都是在 main 函數執(zhí)行前調用,但?+load?比 constructor 更加早一點,因為 dyld(動態(tài)鏈接器,程序的最初起點)在加載 image(可以理解成 Mach-O 文件)時會先通知?objc runtime?去加載其中所有的類,每加載一個類時,它的?+load?隨之調用,全部加載完成后,dyld 才會調用這個 image 中所有的 constructor 方法。
構造器修飾的方法不一定要寫在main的文件里,也可以在其他的文件里。
修飾的方法不一定是一個,也可以多個。
我們可以看到運行結果load->beforeMain->main->afterMain,在上面的main方法里我把autoreleasepool里面的都注釋掉了,是因為它會啟動runloop循環(huán),導致main方法不能運行完畢,afterMain就不能運行,這里為了演示所以注釋掉,所以開發(fā)中__attribute__((destructor))用不到。
7?__attribute__ enable_if
參數靜態(tài)檢查,這個屬性只能用在 C 函數上,修士在方法后面,檢查參數是否正確,錯誤會編譯不通過。
對于這個我還是有點疑惑,enable_if后面的字符串我一直沒搞明白是干什么的,這里就填空字符串吧。
8?__attribute__((overloadable))
用于C函數,修飾同名不同參數的方法,可以同時存在,調用時只需傳遞不同的參數
調用:
overLoad("helloworld");
overLoad(10);
overLoad(YES);
9?__attribute__((cleanup()))
聲明棧中的一個變量,當變量的作用域結束后,調用cleanup里的方法。
這里我們來定義三個變量NSString,int,block
在結尾的輸出中,順序是按照block->int->NSString的順序,這也符合棧后進先出的原則。
10 __attribute__((NSObject))
參照網上的說法會把一個非OC對象的內存管理,當做OC對象來管理。如果沒看懂我們來看例子
看第14行我們用typedef重新定義了CFDictionaryRef,在這里為了體現內存管理,我們寫了兩個屬性cfDictionaryStrong、cfDictionaryWeak,分別用strong、weak修飾。
如果按照正常的邏輯在viewDidLoad里面設值,cfDictionaryStrong會保留。
如上圖,在viewDidLoad里設值,點擊的時候打印,我們看到cfDictionaryStrong打印出結果,cfDictionaryWeak為空。
11?__attribute__((nonnull))
這個修飾在方法的后面,表示方法的參數不能為nil,如果調用參數為nil會發(fā)出警告,太簡單了不寫例子了。
最后筆者第一次寫簡書,希望大家多多支持-.-