Clang Attributes 和 Clang 警告處理

Clang Attributes

iOS開發(fā)工作中愤估,查看官方文檔時(shí)經(jīng)常見到各種系統(tǒng)宏定義,而定義宏時(shí)經(jīng)常一堆以__attribute__(xx) 的語(yǔ)法格式出現(xiàn)沽瘦,這些究竟是何方神圣胧砰,有何作用?本文摘出比較常見的孕讳,做一番解釋。

__attribute__(xx)的語(yǔ)法格式出現(xiàn)巍膘,是 Clang 提供的一些能夠讓開發(fā)者在編譯過(guò)程中參與一些源碼控制的方法厂财。

__attribute__((format(__NSString__, F, A))) 格式化字符串

可以查看 NSLog 的用法:

FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2) NS_NO_TAIL_CALL;

// Marks APIs which format strings by taking a format string and optional varargs as arguments
#if !defined(NS_FORMAT_FUNCTION)
    #if (__GNUC__*10+__GNUC_MINOR__ >= 42) && (TARGET_OS_MAC || TARGET_OS_EMBEDDED)
    #define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))
    #else
    #define NS_FORMAT_FUNCTION(F,A)
    #endif
#endif

__attribute__((deprecated(s)))版本棄用提示
在編譯過(guò)程中能夠提示開發(fā)者該方法或者屬性已經(jīng)被棄用

/** Deprecated, use initWithTimeInterval: instead. */
- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970
    __attribute__((deprecated("Use initWithTimeInterval:")));

__attribute__((availability(os,introduced=m,deprecated=n, obsoleted=o,message=“” __VA_ARGS__)))指明使用版本范圍
os 指系統(tǒng)的版本,m 指明引入的版本峡懈,n 指明過(guò)時(shí)的版本璃饱,o 指完全不用的版本,message 可以寫入些描述信息逮诲。

- (void)method __attribute__((availability(ios,introduced=3_0,deprecated=6_0,obsoleted=7_0,message=“iOS3到iOS7版本可用帜平,iOS7不能用”)));

__attribute__((unavailable(…))) 方法不可用提示

這個(gè)會(huì)在編譯過(guò)程中告知方法不可用,如果使用了還會(huì)讓編譯失敗梅鹦。

__attribute__((unused))

沒有被使用也不報(bào)警告

__attribute__((__warn_unused_result__))

不使用方法的返回值就會(huì)警告,目前 swift3 已經(jīng)支持該特性了冗锁。oc中也可以通過(guò)定義這個(gè)attribute來(lái)支持齐唆。

__attribute__((__availability__(swift, unavailable, message=_msg)))

OC 的方法不能在 Swift 中使用。

__attribute__((cleanup(…)))作用域結(jié)束時(shí)自動(dòng)執(zhí)行一個(gè)指定方法

作用域結(jié)束包括大括號(hào)結(jié)束冻河,return箍邮,goto,break叨叙,exception 等情況锭弊。這個(gè)動(dòng)作是先于這個(gè)對(duì)象的 dealloc 調(diào)用的。

Reactive Cocoa 中有個(gè)比較好的使用范例擂错,@onExit 這個(gè)宏味滞,定義如下:

#define onExit \
    rac_keywordify \
    __strong rac_cleanupBlock_t metamacro_concat(rac_exitBlock_, __LINE__) __attribute__((cleanup(rac_executeCleanupBlock), unused)) = ^

static inline void rac_executeCleanupBlock (__strong rac_cleanupBlock_t *block) {
    (*block)();
}

這樣可以在就可以很方便的把需要成對(duì)出現(xiàn)的代碼寫在一起了。同樣可以在 Reactive Cocoa 看到其使用

if (property != NULL) {
        rac_propertyAttributes *attributes = rac_copyPropertyAttributes(property);
        if (attributes != NULL) {
            @onExit {
                free(attributes);
            };

            BOOL isObject = attributes->objectClass != nil || strstr(attributes->type, @encode(id)) == attributes->type;
            BOOL isProtocol = attributes->objectClass == NSClassFromString(@“Protocol”);
            BOOL isBlock = strcmp(attributes->type, @encode(void(^)())) == 0;
            BOOL isWeak = attributes->weak;

            shouldAddDeallocObserver = isObject && isWeak && !isBlock && !isProtocol;
        }
    }

可以看出 attributes 的設(shè)置和釋放都在一起使得代碼的可讀性得到了提高钮呀。

__attribute__((overloadable))方法重載
能夠在 c 的函數(shù)上實(shí)現(xiàn)方法重載剑鞍。即同樣的函數(shù)名函數(shù)能夠?qū)Σ煌瑓?shù)在編譯時(shí)能夠自動(dòng)根據(jù)參數(shù)來(lái)選擇定義的函數(shù)

__attribute__((overloadable)) void printArgument(int number){
    NSLog(@“Add Int %i”, number);
}

__attribute__((overloadable)) void printArgument(NSString *number){
    NSLog(@“Add NSString %@“, number);
}

__attribute__((overloadable)) void printArgument(NSNumber *number){
    NSLog(@“Add NSNumber %@“, number);
}

__attribute__((objc_designated_initializer))指定內(nèi)部實(shí)現(xiàn)的初始化方法

如果是 objc_designated_initializer 初始化的方法必須調(diào)用覆蓋實(shí)現(xiàn) super 的 objc_designated_initializer 方法。
如果不是 objc_designated_initializer 的初始化方法爽醋,但是該類有 objc_designated_initializer 的初始化方法蚁署,那么必須調(diào)用該類的 objc_designated_initializer 方法或者非 objc_designated_initializer 方法,而不能夠調(diào)用 super 的任何初始化方法蚂四。
__attribute__((objc_subclassing_restricted)) 指定不能有子類

相當(dāng)于 Java 里的 final 關(guān)鍵字光戈,如果有子類繼承就會(huì)出錯(cuò)哪痰。

__attribute__((objc_requires_super))子類繼承必須調(diào)用 super

聲明后子類在繼承這個(gè)方法時(shí)必須要調(diào)用 super,否則會(huì)出現(xiàn)編譯警告久妆,這個(gè)可以定義一些必要執(zhí)行的方法在 super 里提醒使用者這個(gè)方法的內(nèi)容時(shí)必要的晌杰。

__attribute__((const)) 重復(fù)調(diào)用相同數(shù)值參數(shù)優(yōu)化返回

用于數(shù)值類型參數(shù)的函數(shù),多次調(diào)用相同的數(shù)值型參數(shù)镇饺,返回是相同的乎莉,只在第一次是需要進(jìn)行運(yùn)算,后面只返回第一次的結(jié)果奸笤,這時(shí)編譯器的一種優(yōu)化處理方式惋啃。

__attribute__((constructor(PRIORITY)))__attribute__((destructor(PRIORITY)))

PRIORITY 是指執(zhí)行的優(yōu)先級(jí),main 函數(shù)執(zhí)行之前會(huì)執(zhí)行 constructor监右,main 函數(shù)執(zhí)行后會(huì)執(zhí)行 destructor边灭,+load 會(huì)比 constructor 執(zhí)行的更早點(diǎn),因?yàn)閯?dòng)態(tài)鏈接器加載 Mach-O 文件時(shí)會(huì)先加載每個(gè)類健盒,需要 +load 調(diào)用绒瘦,然后才會(huì)調(diào)用所有的 constructor 方法。

通過(guò)這個(gè)特性扣癣,可以做些比較好玩的事情惰帽,比如說(shuō)類已經(jīng) load 完了,是不是可以在 constructor 中對(duì)想替換的類進(jìn)行替換父虑,而不用加在特定類的 +load 方法里该酗。

Clang 警告處理

先看看這個(gè)

#pragma clang diagnostic push
#pragma clang diagnostic ignored “-Wdeprecated-declarations”
        sizeLabel = [self sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping];
#pragma clang diagnostic pop

如果沒有#pragma clang 這些定義,會(huì)報(bào)出 sizeWithFont 的方法會(huì)被廢棄的警告士嚎,這個(gè)加上這個(gè)方法當(dāng)然是為了兼容老系統(tǒng)呜魄,加上 ignored “-Wdeprecated-declarations” 的作用是忽略這個(gè)警告。通過(guò) clang diagnostic push/pop 可以靈活的控制代碼塊的編譯選項(xiàng)莱衩。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末爵嗅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子笨蚁,更是在濱河造成了極大的恐慌睹晒,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赚窃,死亡現(xiàn)場(chǎng)離奇詭異册招,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)勒极,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門是掰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人辱匿,你說(shuō)我怎么就攤上這事键痛§挪剩” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵絮短,是天一觀的道長(zhǎng)江兢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)丁频,這世上最難降的妖魔是什么杉允? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮席里,結(jié)果婚禮上叔磷,老公的妹妹穿的比我還像新娘。我一直安慰自己奖磁,他們只是感情好改基,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咖为,像睡著了一般秕狰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上躁染,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天鸣哀,我揣著相機(jī)與錄音,去河邊找鬼吞彤。 笑死诺舔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的备畦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼许昨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼懂盐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起糕档,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤莉恼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后速那,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俐银,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年端仰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捶惜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荔烧,死狀恐怖吱七,靈堂內(nèi)的尸體忽然破棺而出汽久,到底是詐尸還是另有隱情,我是刑警寧澤踊餐,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布景醇,位于F島的核電站,受9級(jí)特大地震影響吝岭,放射性物質(zhì)發(fā)生泄漏三痰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一窜管、第九天 我趴在偏房一處隱蔽的房頂上張望散劫。 院中可真熱鬧,春花似錦微峰、人聲如沸舷丹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)颜凯。三九已至,卻和暖如春仗扬,著一層夾襖步出監(jiān)牢的瞬間症概,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工早芭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彼城,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓退个,卻偏偏與公主長(zhǎng)得像募壕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子语盈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容