多用類型常量, 少用#define預(yù)處理命令

在開發(fā)中我們經(jīng)常要定義常量,比如設(shè)定一個(gè)動(dòng)畫執(zhí)行的時(shí)間,一般我們會這樣寫:

#define ANIMATION_DURATION 3.3

這條預(yù)處理命令會把源代碼中的ANIMATION_DURATION字符串替換為3.3.不過這樣做并不優(yōu)雅.原因是:

  • 這樣定義出來的常量沒有類型信息(持續(xù)一詞應(yīng)該與時(shí)間有關(guān),但是未指明)
  • 預(yù)處理命令會把所有的ANIMATION_DURATION全部替換成3.3(假設(shè)此命令聲明在頭文件里,那么所有引入這個(gè)頭文件的代碼,其ANIMATION_DURATION都會被替換)

有個(gè)辦法比用預(yù)處理命令來定義常量好,比如我們定義了一個(gè)類型為NSTimeInterval的常量:

static const NSTimeInterval kAnimationDuration = 3.3

這樣定義常量,好處不言而喻.這里還要注意的是常用的命名方法:若常量局限于某"編譯單元"(實(shí)現(xiàn)文件.m)內(nèi),則在前面加字母k,若是常量在類之外可見,則通常以類名為前綴.同時(shí)定義常量的位置也很重要,我們常常喜歡在頭文件里聲明預(yù)處理命令,這樣做真的是糟糕透了.特別是當(dāng)常量名稱可能相互沖突時(shí)更是令人抓狂.

比如ANIMATION_DURATION這個(gè)常量名就不該用在頭文件中,因?yàn)樗幸氪祟^文件的其他文件中都會出現(xiàn)這個(gè)名字.其實(shí)就連用static const定義的那個(gè)常量也不應(yīng)該出現(xiàn)在頭文件里.以為OC中是沒有"名稱空間"這一概念的.所有這樣做等于聲明了一個(gè)kAnimationDuration全局變量(準(zhǔn)確的講應(yīng)該加上類名CWGViewClassAnimationDuration).當(dāng)然如果不打算公開某個(gè)常量.則應(yīng)該將其定義到實(shí)現(xiàn)文件.m中.

變量一定要同時(shí)使用static和const來聲明.如果試圖修改由const修飾符聲明的變量,編譯器會報(bào)錯(cuò)的,有時(shí)這正是我們想要的結(jié)果.static修飾符意味著改變量盡在定義此變量的"編譯單元"可見.編譯器每收到一個(gè)編譯單元,就輸出一份"目標(biāo)文件",在OC中,"編譯單元"一詞通常指每個(gè)類的實(shí)現(xiàn)文件.m.因此在代碼中聲明一個(gè)kAnimationDuration變量,其作用域僅限于由CWGAnimatedView.m所生產(chǎn)的目標(biāo)文件.假如聲明時(shí)不帶static,那么編譯器就會創(chuàng)建一個(gè)外部符號,此時(shí)若另外一個(gè)編譯單元中也聲明了同名變量,那么編譯器就會拋出一條錯(cuò)誤信息:

duplicate symbol _kAnimationDuration in:
   CWGAnimatedView.o
   CWGOtherView.o

但是一個(gè)變量即聲明為:static,又聲明為const,那么編譯器就不會創(chuàng)建外部符號.

有時(shí)候我們需要對外公開某個(gè)常量,比方說,在類代碼中調(diào)用NSNotificationCenter以通知他人,用一個(gè)對象來派發(fā)通知,令其他要接收通知的對象向該對象注冊,這樣就能實(shí)現(xiàn)此功能了,派發(fā)通知時(shí),需要使用字符串來表示此項(xiàng)通知的名稱,而這個(gè)名字就可以聲明為一個(gè)對外可見的常值變量,這樣的話,注冊者無需知道實(shí)際字符串值,只需以常值變量來注冊自己想要接受的通知即可.

此類常量需要放在"全局符號表"中,以便可以在定義該常量的編譯單元之外使用.

// In the header file(.h)
extern NSString *const CWGViewStringConstant;
extern const NSTimeInterval CWGAnimationViewDuration;

// In the implementation file(.m)
NSString *const CWGViewStringConstant = @"VALUE";
const NSTimeInterval CWGAnimationViewDuration = 3.3;

這個(gè)常量在頭文件中"聲明",且在實(shí)現(xiàn)文件中"定義".注意const修飾符的位置,常量定義應(yīng)該從右至左解讀,所以在示例中,CWGStringConstant就是"一個(gè)常量, 而這個(gè)常量是指針, 指向NSString對象".這與需求是相符的,因?yàn)槲覀儾幌M腥烁淖兇酥羔槼A?使其指向另外一個(gè)NSString對象.

還要說一點(diǎn)就是因?yàn)榉栆旁谌址柋碇?所以一定要注意常量的命名規(guī)范.避免名稱沖突,最好使用與之相關(guān)的類名做前綴.系統(tǒng)框架中一般都是這么做的.

使用上述定義常量的方法,編譯器會確保常量值不變,而采用#define預(yù)處理指令定義的常量可能會無意中被他人修改.從而導(dǎo)致各個(gè)部分引用的值不同,引起難以排查的bug.

總結(jié):

  • 不要使用#define預(yù)處理指令來定義常量,因?yàn)檫@樣的常量不包括類型信息,編譯器只會在編譯前執(zhí)行查找和替換操作,即使有人重新定義了常量值,編譯器也不會發(fā)出警告,這樣會導(dǎo)致應(yīng)用程序中的常量值不一致.

  • 在實(shí)現(xiàn)文件.m中使用static const來定義"只在編譯單元張可見的常量",由于此類常量不在全局符號表中,所以無須為其名稱加前綴.

  • 在頭文件中使用extern來聲明全局常量,并在相關(guān)文件中定義其值,這種常量要出現(xiàn)在全局符號表中,所以其名稱應(yīng)該加以區(qū)分,通常用與之相關(guān)的類名做前綴.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜂嗽,一起剝皮案震驚了整個(gè)濱河市苫亦,隨后出現(xiàn)的幾起案子秋柄,更是在濱河造成了極大的恐慌,老刑警劉巖抵怎,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異省核,居然都是意外死亡掂僵,警方通過查閱死者的電腦和手機(jī)航厚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锰蓬,“玉大人幔睬,你說我怎么就攤上這事∏叟ぃ” “怎么了麻顶?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舱卡。 經(jīng)常有香客問我澈蚌,道長,這世上最難降的妖魔是什么灼狰? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任宛瞄,我火速辦了婚禮,結(jié)果婚禮上交胚,老公的妹妹穿的比我還像新娘份汗。我一直安慰自己,他們只是感情好蝴簇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布杯活。 她就那樣靜靜地躺著,像睡著了一般熬词。 火紅的嫁衣襯著肌膚如雪旁钧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天互拾,我揣著相機(jī)與錄音歪今,去河邊找鬼。 笑死颜矿,一個(gè)胖子當(dāng)著我的面吹牛寄猩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骑疆,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼田篇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了箍铭?” 一聲冷哼從身側(cè)響起泊柬,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诈火,沒想到半個(gè)月后兽赁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年闸氮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剪况。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蒲跨,死狀恐怖译断,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情或悲,我是刑警寧澤孙咪,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站巡语,受9級特大地震影響翎蹈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜男公,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一荤堪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枢赔,春花似錦澄阳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至速梗,卻和暖如春肮塞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姻锁。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工枕赵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屋摔。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓烁设,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钓试。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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