最近在工程里看到很多不規(guī)范的使用,于是來寫一篇博客來讓不是很清楚的小朋友們蜈彼,少埋點(diǎn)坑筑辨。
-
首先,預(yù)處理命令他不是一個常量P夷妗9髟!还绘!
我們來看一段代碼
#define avatar @"60"
if (false) {
#define avatar @"80"
}
NSLog(avatar);
這段代碼會輸出多少楚昭,我們將“avatar”定義為了60,然后在一個永遠(yuǎn)不會執(zhí)行的代碼里面重新定義了“avatar”為80蚕甥,if語句中的代碼永遠(yuǎn)不會執(zhí)行哪替,但是在編譯時期,編譯器會編譯這段代碼菇怀,而這個時候編譯器就會將avatar這個名字替換為@“80”凭舶,所以這段代碼最后的輸出結(jié)果就是80。
當(dāng)然這個時候編譯器是會有一個警告的爱沟,但是不知道有多少同學(xué)會忽略這個警告帅霜。或者你會告訴我你對警告十分敏感呼伸,不會放過他的身冀,但是記住你不是一個人在寫代碼,可能在別人的頁面他給你重新定義了你的define括享,給你挖了一個大坑搂根,還找不著.........
-
用const來定義一個常量
const修飾符定義的變量是不可變的,比如說你需要定義一個動畫時間的常量铃辖,你可以這么做:
static const NSTimeInterval kAnimateDuration = 0.3;
當(dāng)你試圖去修改“ kAnimateDuration”的值的時候剩愧,編譯器會報錯。更加重要的是用這種方法定義的常量是帶有類型信息的娇斩,而這點(diǎn)則是define不具備的仁卷。
也許你已經(jīng)發(fā)現(xiàn)了,如果你像這樣定義:
static const NSString * kUserName = @"StrongX";
你是可以修改userName的值的犬第,(說好的常量呢~~~)
首先我們需要確定的是以下兩種寫法是一樣的:
static NSString const * kUserName = @"StrongX";
static const NSString * kUserName = @"StrongX";
也就是說const放在類型前還是類型后是一樣的效果锦积。然后不同效果的是下面這種寫法:
static NSString * const kUserName = @"StrongX";
const 修飾的是他右邊的部分,也就是說:
static NSString const * kUserName = static NSString const (* kUserName )
static NSString * const kUserName = static NSString * const (kUserName)
當(dāng)const修飾的是(userName)的時候歉嗓,不可變的是userName;“*”在C語言中表示
指針指向符丰介,也就是說這個時候userName指向的內(nèi)存塊地址不可變,而內(nèi)存保存的內(nèi)容是可變的,我們來做個嘗試:
NSLog(@"內(nèi)存地址: %x",& kUserName);
kUserName = @"superXLX";
NSLog(@"內(nèi)存地址: %x",& kUserName);
以上NSLog會打印*userName指向的內(nèi)存塊地址基矮,而他的輸出是:
我們已經(jīng)發(fā)現(xiàn)當(dāng)我們改變內(nèi)存的內(nèi)存的時候他的地址并沒有發(fā)生改變淆储,也就是說這是符合“const”修飾符的規(guī)定的。
而當(dāng)我們的修飾符是這樣的時候:
static NSString * const kUserName = @"StrongX";
我們則無法改變userName的值家浇。
所以當(dāng)我們需要定義一個不可變的常量的時候 本砰,我們還是需要將“const”修飾符放到“*”指針指向符后邊才對。
-
一定要同時使用static和const來定義你的變量
上面已經(jīng)說了const是用來定義一個常量钢悲。而static在C語言中(OC中延用)則表明此變量只在改變量的輸出文件中可用(.m文件)点额,如果你不加“static”符號,那么編譯器就會對該變量創(chuàng)建一個“外部符號”莺琳,后果是什么呢还棱?
你可以嘗試在不同編譯文件中加入以下代碼:
NSString * const kUserName = @"StrongX";
可能盡管文件之間并沒有相互引用,不存在屬性名重復(fù)的問題(因為這并不是一個屬性惭等,這是一個外部符號),但是編譯器還是報錯了:
他會告訴你在兩個目標(biāo)文件(.0文件是.m文件編譯后的輸出文件)有一個重復(fù)的符號珍手。(OC中沒有類似C++中的名字空間的概念)
所以當(dāng)你在你自己的.m文件中需要聲明一個只有你自己可見的局部變量(k開頭)的變量的時候一定要同時使用“static”和“const”兩個符號。
-
定義工程中的全局變量
在我們的工程中一定會定義很多全局常量辞做,很多人的做法是會創(chuàng)建一個“ constant.h”文件琳要,在這個文件中用#define聲明許多常量,然后將這個頭文件引入“pch”文件中秤茅,不能說這么做不對稚补,但是如同上面說的那樣define可能被修改,當(dāng)然在命名規(guī)范的情況下這種情況很少出現(xiàn)框喳,并且這樣做的效率很高课幕。
然而蘋果更推薦另外一種做法:"extern",這樣做的優(yōu)勢是保持常量絕對不會被修改五垮,并且一定初始化還帶有類型信息乍惊。
我們在"constants.h"文件中,聲明常量:
extern NSString *const XUserName;
然后在“constants.m”中定義他:
NSString *const XUserName = @"StrongX";
用“extern”定義的常量必須也只能初始化一次放仗,不滿足必須以及只能一次的條件那么編譯器就會提醒你污桦。在定義全局變量的時候需要要注意你的命名,你可以使用規(guī)定好的前綴來命名匙监。
“define”和“extern”各有各的優(yōu)勢,不過我個人還是比較推薦使用“extern”.(因為之前在一個工程中被define坑慘了——小作!)亭姥。