用__Attribute__做點好玩的事情:第一篇

之前寫過一篇attribute((constructor))用法探究,當時是在看代碼的時候,對它產(chǎn)生了偶遇.而這幾天,越發(fā)發(fā)現(xiàn)這個__attribute__的強大.作為一個iOS開發(fā)者,我試著總結(jié)了一下這個在我們?nèi)粘i_發(fā)中的應(yīng)用.

從 __Nonull說起

蘋果在Xcode6.3中引入了這個特性, 目的在于為Swift混編時,讓編譯器知道這個Object-C對象是不是可選的.使用方法如下:

-(void)openPath:(NSString * _Nonnull)path;

今天在llvm的文檔中,發(fā)現(xiàn)了一段這樣的描述:


The nonnull attribute indicates that some function parameters must not be null, and can be used in several different ways. It’s original usage (from GCC) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. 

大概意思是:
nonnull這個屬性表示函數(shù)的參數(shù)不能為空,并且這個屬性有幾種不同的使用方式,最基本的用法就是用來修飾函數(shù)(或者OC的方法),使用一個用逗號分隔的參數(shù)表來表明函數(shù)或者方法的那個哪個參數(shù)非空.

還是代碼比較明顯:

-(void)openFile:(NSString*)file __attribute__((nonnull(1)));

當我們這么使用時候:

 [self openFile:nil];

就會得到這么一個警告:


20160928147504628663285.jpg

幾個注意點:

  • nonull的參數(shù)從1開始
  • OC的隱含參數(shù)self_cmd不計入?yún)?shù)范圍

_Nonnull_Nullable在文檔中也有說明:

_Nonnull修飾指針類型,表示這個指針類型不會把null當做有意義的參數(shù),用法如下:

int fetch(int * _Nonnull ptr);

_Nullable修飾指針類型,表示這個指針類型可以是null的,用法如下:

int fetch_or_zero(int * _Nullable ptr);

注意:它們只能修飾指針類型的參數(shù).

RAC中的 @onExit

用過RAC的應(yīng)該對這個關(guān)鍵字不陌生,它實現(xiàn)了,當一個變量作用域結(jié)束時,調(diào)用指定的block,查看這個宏的定義:

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

這個rac_keywordfiy的定義如下:

#if DEBUG
#define rac_keywordify autoreleasepool {}
#else
#define rac_keywordify try {} @catch (...) {}
#endif

這也是為什么onExit使用的時候,前面需要添加一個@,因為只有這樣才能湊成完整的@autoreleasepool或者@try {}.
言歸正傳,我們關(guān)注這個部分:

__attribute__((cleanup(rac_executeCleanupBlock), unused))

先說簡單的,unused表示函數(shù)或者變量可能不用,防止編譯器產(chǎn)生警告.
而這個__attribute__((cleanup(...)))用來修飾變量,當變量的作用域結(jié)束的時候,就調(diào)用參數(shù).參數(shù)是一個函數(shù),當然,也可以是block,RAC里面就是這么干的.用代碼來說明:

static void stringCleanUp(__strong NSString **string) {
    NSLog(@"%@", *string);
}

static void cleanupBlock(__strong void(^*block)(void)) {
    (*block)();
};

- (void)viewDidLoad {
    [super viewDidLoad];

    __strong NSString * myname  __attribute__((cleanup(stringCleanUp), unused)) = @"kenny";
    
    __strong void(^block)(void) __attribute__((cleanup(cleanupBlock), unused)) = ^{
        NSLog(@"gonna released");
    };
}

需要注意的是cleanup的參數(shù)方法:它的參數(shù)是修飾的變量的地址.所以會用到了*block**string,另外:

對于指向objc對象的指針(id *),如果不強制聲明__strong默認是__autoreleasing,造成類型不匹配

參考鏈接:

Common-Variable-Attributes

http://blog.sunnyxx.com/2014/09/15/objc-attribute-cleanup/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 8,107評論 0 27
  • attribute是GNU C特色之一,在iOS用的比較廣泛.系統(tǒng)中有許多地方使用到. attribute可以設(shè)置...
    youngyunxing閱讀 28,671評論 7 66
  • 原文地址:C語言函數(shù)調(diào)用棧(一)C語言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過程可看作連續(xù)的函數(shù)調(diào)用。當一個函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,956評論 1 19
  • 一曲俗人言,兩抹閑人淚, 酒肉穿腸過,觥倒知不知? 挽袖濕衣,行云流水, 俯仰之間,仕女石上。 遠眺目下,塵起拂光...
    音驪繪閱讀 330評論 1 1
  • 2016年元月2日,在這冬日里走在這鹿城的小巷里,在時光飛逝咖啡館里欣賞著這話劇--《暗戀桃花源》,這場景這人...
    時間yi閱讀 860評論 1 1

友情鏈接更多精彩內(nèi)容