華山論劍之淺談iOS的宏定義以及內(nèi)聯(lián)函數(shù)的使用

你帶著一個故事去聽一首歌感覺會不一樣,你帶著一個故事去找一首歌心情會不一樣。


宏定義的簡介


宏定義是C提供的三種預(yù)處理功能的其中一種,這三種預(yù)處理包括:宏定義、文件包含、條件編譯.

1. 不帶參數(shù)的宏定義:

格式: #define 標(biāo)識符 字符串

說明:

(1)宏名一般用大寫

(2)使用宏可提高程序的通用性和易讀性,減少不一致性,減少輸入錯誤和便于修改。例如:數(shù)組大小常用宏定義

(3)預(yù)處理是在編譯之前的處理,而編譯工作的任務(wù)之一就是語法檢查,預(yù)處理不做語法檢查。

(4)宏定義末尾不加分號;

(5)宏定義寫在函數(shù)的花括號外邊,作用域為其后的程序,通常在文件的最開頭。

(6)可以用#undef命令終止宏定義的作用域

(7)宏定義可以嵌套

(8)字符串" "中永遠(yuǎn)不包含宏

(9)宏定義不分配內(nèi)存,變量定義分配內(nèi)存。


2. 帶參數(shù)的宏定義:

除了一般的字符串替換,還要做參數(shù)代換

格式:   #define 宏名(參數(shù)表) 字符串

例如:#define S(a,b) a*b

(1)實參如果是表達(dá)式容易出問題

(2)宏名和參數(shù)的括號間不能有空格

(3)宏替換只作替換,不做計算,不做表達(dá)式求解

(4)函數(shù)調(diào)用在編譯后程序運(yùn)行時進(jìn)行,并且分配內(nèi)存。宏替換在編譯前進(jìn)行,不分配內(nèi)存

(5)宏的啞實結(jié)合不存在類型,也沒有類型轉(zhuǎn)換。

(6)函數(shù)只有一個返回值,利用宏則可以設(shè)法得到多個值

(7)宏展開使源程序變長,函數(shù)調(diào)用不會

(8)宏展開不占運(yùn)行時間,只占編譯時間,函數(shù)調(diào)用占運(yùn)行時間(分配內(nèi)存、保留現(xiàn)場、值傳遞、返回值)


iOS中常用的宏定義


上面說到宏定義主要分為參數(shù)宏和非參數(shù)宏,接下來,我們就看一下,在iOS開發(fā)過程中我們常用的一些宏定義.

  • 尺寸相關(guān)

//主屏幕的寬高
#define KmainHight  [UIScreen mainScreen].bounds.size.height

#define KmainWidth  [UIScreen mainScreen].bounds.size.width

//導(dǎo)航欄高度
#define KnavigationBarHeight (44)

//標(biāo)簽欄高度
#define KtabBarHeight (49)


  • 顏色相關(guān)
//普通顏色
#define KmyColor(R,G,B) [UIColor colorWithRed:R/255.0 green:G/255.0 blue:B/255.0 alpha:1.0]

// 隨機(jī)顏色
#define KrandomColor   [UIColor colorWithRed:arc4random_uniform(256) / 255.0 green:arc4random_uniform(256) / 255.0 blue:arc4random_uniform(256) / 255.0 alpha:1]

  • 語言相關(guān)
//獲取當(dāng)前語言
#define KcurrentLanguage ([[NSLocale preferredLanguages] objectAtIndex:0])
  • 系統(tǒng)版本相關(guān)
//主要用于判斷當(dāng)前iOS版本號,對其棄用或者未出現(xiàn)的方法進(jìn)行區(qū)別對待
#define KcurrentSystemVersion [[UIDevice currentDevice] systemVersion]  

  • 手機(jī)型號相關(guān)
//iPhone5
#define IPHONE5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO)

//iPhone6
#define IPHONE6 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(750, 1334), [[UIScreen mainScreen] currentMode].size) : NO)

//iPhone6 Plus
#define IPHONE6_Plus ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2208), [[UIScreen mainScreen] currentMode].size) : NO)

//Pad
#define KisPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)

  • 模擬器相關(guān)
/判斷是真機(jī)還是模擬器  
#if TARGET_OS_IPHONE  

//真機(jī)
#endif  
  
#if TARGET_IPHONE_SIMULATOR  

//模擬器

#endif  
  • 國際化相關(guān)(國際化相關(guān)知識不懂點(diǎn)這里)
#define LocalString(string)     NSLocalizedString(string, nil)

  • 引用相關(guān)
//弱引用
#define KweakSelf(type)  __weak typeof(type) weak##type = type;

//強(qiáng)引用
#define KstrongSelf(type)  __strong typeof(type) type = weak##type;
  • 沙盒相關(guān)
//獲取沙盒主路徑
#define KhomePath    NSHomeDirectory()

//獲取沙盒 Temp
#define KtempPath NSTemporaryDirectory()

//獲取沙盒 Document
#define KdocumentPath    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]

//獲取沙盒 Cache
#define KcachePath [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]

  • 打印相關(guān)
//對象打印
#define KobjectLog(object)  NSLog(@"%@",(object));

//整型數(shù)字打印
#define KintNumberLog(number)  NSLog(@"%d",(number));

//float數(shù)字打印
#define KfloatNumberLog(number)  NSLog(@"%f",(number));

  • 上線相關(guān)

// 自定義NSLog,在debug模式下打印,在release模式下取消一切NSLog(上線時候使用推薦:??????????)

#ifdef DEBUG

#define NSLog(FORMAT, ...) fprintf(stderr,"%s:%d\t%s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);

#else

#define NSLog(FORMAT, ...) nil

#endif


內(nèi)聯(lián)函數(shù)的簡介及其使用


當(dāng)?shù)谝淮谓佑|內(nèi)聯(lián)函數(shù)的時候,我認(rèn)為內(nèi)斂函數(shù)就是宏定義,后來經(jīng)過度娘的循循教導(dǎo),我才知道對于內(nèi)聯(lián)函數(shù)原來是另有乾坤呀.
為什么要使用內(nèi)聯(lián)函數(shù)呢?其實主要是宏定義雖然簡單易懂,但是容易出錯,下面我們就舉例子說明.
比如下面的這個宏定義,其實很簡單,就是比較兩個數(shù)的大小.

#define Kmax(a, b)  (a) > (b) ? (a) : (b)

然后,我們這樣調(diào)用

int result = Kmax(i, j) + 2 ; 

其實結(jié)果就成了

 result = (i) > (j) ? (i) : (j) + 2 ; 

而我們需要的是

 result = ( (i) > (j) ? (i) : (j) ) + 2 ; 

這樣就離我們需要的期望隔著失之毫厘謬以千里....好了,這時候有人就說了,如下改動不就沒有任何問題了?但是真的沒有問題了嗎?

#define Kmax(a, b)   ((a) > (b) ? (a) : (b))

如上的修改的確可以修改上面的問題,但是我們?nèi)缦率褂?還是存在問題的

 result = Kmax(i++, j); 

那么預(yù)處理會處理成如下,跟我們的預(yù)想的結(jié)果還是不一致...

 result = (i++) > (j) ? (i++) : (j); 

看到上面的問題這么多,相信你們的頭和我一樣是大大的,那么這時候就我們的豬腳--->內(nèi)聯(lián)函數(shù)來解決問題了,我們先看一下內(nèi)聯(lián)函數(shù)的結(jié)構(gòu).

NS_INLINE (函數(shù)類型,如void,int,id) 函數(shù)名 ( 參數(shù)a,參數(shù)b,..... ) {
..........(函數(shù)實現(xiàn))..........
}

就拿上面的比較方法,我們可以直接寫在PCH文件中.代碼如下.(注意:NS_INLINE是內(nèi)聯(lián)函數(shù)的標(biāo)志,同時要使用內(nèi)聯(lián)函數(shù),需要導(dǎo)入Foundation框架)這樣就完美的解決了上面的問題.

#import <Foundation/Foundation.h>

NS_INLINE int max( int a ,int b){
    
    return a>b?a:b;
    
}

下面接著是分享給大家的一個內(nèi)聯(lián)函數(shù)的應(yīng)用,一個自定義內(nèi)聯(lián)函數(shù)彈窗.(注意:因為UIAlertView被棄用的問題,所以會爆一個黃,但是真的很好用,所以就分享一下)

#import <UIKit/UIKit.h>

#import <Foundation/Foundation.h>


NS_INLINE void tipWithMessage(NSString *message){
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil, nil];
        
        [alerView show];
        
        [alerView performSelector:@selector(dismissWithClickedButtonIndex:animated:) withObject:@[@0, @1] afterDelay:0.9];
        
    });
    
}


下面對于調(diào)用也是非常的簡單,如下在-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 方法中,調(diào)用彈窗函數(shù).

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    tipWithMessage(@"世界,你好!");

}

下面是效果圖.


內(nèi)聯(lián)函數(shù)的注意事項


內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價,僅僅省去了函數(shù)調(diào)用的開銷,從而提高函數(shù)的執(zhí)行效率。如果執(zhí)行函數(shù)體內(nèi)代碼的時間,相比于函數(shù)調(diào)用的開銷較大,那么效率的收獲會很少。另一方面,每一處內(nèi)聯(lián)函數(shù)的調(diào)用都要復(fù)制代碼,將使程序的總代碼量增大,消耗更多的內(nèi)存空間。以下情況不宜使用內(nèi)聯(lián):
  • (1)如果函數(shù)體內(nèi)的代碼比較長,使用內(nèi)聯(lián)將導(dǎo)致內(nèi)存消耗代價較高。
  • (2)如果函數(shù)體內(nèi)出現(xiàn)循環(huán),那么執(zhí)行函數(shù)體內(nèi)代碼的時間要比函數(shù)調(diào)用的開銷大。


總結(jié)


關(guān)于iOS的宏定義以及內(nèi)聯(lián)函數(shù)的使用就說到這里,兩者說起來各有利弊,但是不得不說的是有了宏定義以及內(nèi)聯(lián)函數(shù)之后,對開發(fā)是一個不少的助力.好了,今天就說到這里了,希望文章對您有所幫助.碼字不易,跪求點(diǎn)贊..??
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,960評論 2 373

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