我們?cè)趇os開發(fā)中都會(huì)經(jīng)常定義常量挤渔,比如說窗市,在一個(gè)頁面上播放一個(gè)動(dòng)畫先慷,在很多開發(fā)者來說都會(huì)把八方動(dòng)畫的時(shí)間提取為一個(gè)常量,我想想很多人都會(huì)這樣做咨察,包括我自己论熙。
define ANIMATION_DURATTON 1.5
這段預(yù)處理指令會(huì)吧代碼中的ANIMATION_DURATTON字符串替換成1.5,不過這樣定義出來的常量沒有類型信息摄狱,預(yù)處理過程中會(huì)把碰到的所有的ANIMATION_DURATTON替換成為1.5脓诡,這樣的話素跺,假設(shè)此指令生命在某個(gè)頭文件中,那么所有引入這個(gè)頭文件的代碼誉券,其ANIMATION_DURATTON都會(huì)被替換指厌。
想要解決這個(gè)問題最好的辦法就是設(shè)法利用編譯器的某些特性,有個(gè)辦法比用預(yù)處理指令來定義常量更好踊跟,如例:
static const NSSTimeInterval kAnimationDuration = 1.5;
此方式定義的常量包含類型信息踩验,其好處是清楚的描述了常量的含義,由此可以知道該常量的類型為NSSTimeInterval商玫。
定義常量的位置很重要箕憾,我們總喜歡在頭文件里聲明預(yù)處理指令,這樣做真的很糟糕拳昌,當(dāng)常量名稱有可能互相沖突時(shí)更是如此袭异。例如,ANIMATION_DURATTON這個(gè)常量名就不該定義在頭文件炬藤,應(yīng)為所喲引入這份頭文件的其他文件都會(huì)出現(xiàn)這個(gè)名字御铃。其實(shí)就連用static const定義的那個(gè)常量也不應(yīng)該出現(xiàn)在頭文件里。因?yàn)镺bjective-C沒有“名稱空間”這一概念沈矿,所以那樣做就等于聲明了一個(gè)名叫kAnimationDuration全局變量上真,因此名稱必須加上前綴,以表明所屬的類羹膳。
如果不打算公開某個(gè)常量睡互,就應(yīng)該在使用該常量的實(shí)現(xiàn)文件里定義,例如:
//EOCAnimatedView.h
import <UIKit/UIKit.h>
@interface EOCAnimatedView : UIView
-(void)animate;
@end
//EOCAnimatedView.m
import "EOCAnimatedView.h"
static const NSSTimeInterval kAnimationDuration = 1.5;
@implementation EOCAnimatedView
-(void)animate{
}
@end
變量一定要同時(shí)用static和const來聲明陵像,事實(shí)上就珠,一個(gè)變量既聲明為static,又聲明為const醒颖,那么編譯器根本不會(huì)創(chuàng)建符號(hào)妻怎,而會(huì)像#define預(yù)處理指令一樣把所有遇到的變量都替換成常值,不過要記住图贸,用這種方式定義的常量帶有類型信息蹂季。
有時(shí)候需要對(duì)外公開一個(gè)常量,此類常量需要放在“全局符號(hào)表”中疏日,以便可以在定義該常量的編譯單元之外使用偿洁,因此其定義方式與上例演示的static const有所不一樣:
//In the header file
extern NSString *const EOCStringConstant;
//In the implementation file
NSString *const EOCStringConstant=@"VALUE";
這個(gè)常量在頭文件中“聲明”,且在實(shí)現(xiàn)文件中“定義”沟优,const修飾符在常量類型中的位置涕滋,常量從右至左解讀。編譯器看到頭文件中的extern關(guān)鍵字挠阁,就能明白如何明白在引入此文件的代碼中處理該常量了宾肺。這個(gè)關(guān)鍵字就會(huì)告訴編譯器溯饵,在全局符號(hào)表中將會(huì)有一個(gè)名叫EOCStringConstant的符號(hào),編譯器無需查看其定義锨用,既允許此代碼使用此常量丰刊,因?yàn)樗喇?dāng)鏈接成二進(jìn)制文件之后,肯定能找到這個(gè)常量增拥。
此類常量必須要定義啄巧,且只能定義一次,通常將其定義在與聲明該常量的頭文件相關(guān)的實(shí)現(xiàn)文件里掌栅,由實(shí)現(xiàn)文件生成目標(biāo)文件時(shí)秩仆,編譯器會(huì)在“數(shù)據(jù)段”為字符串分配存儲(chǔ)空間。連接器會(huì)把此目標(biāo)文件和其他的目標(biāo)文件相鏈接猾封,以生成最終的二進(jìn)制文件澄耍,凡使用到EOCStringConstant這個(gè)全局符號(hào)的地方,鏈接器都能將其解析晌缘。
注意常量的名字齐莲,為避免名稱沖突,最好使用與之相關(guān)的類名作為前綴枚钓。
這樣定義的常量?jī)?yōu)于使用#define預(yù)處理命令铅搓,因?yàn)榫幾g器確保常量的值不會(huì)變,總之勿使用預(yù)處理指令定義常量搀捷,而應(yīng)該用戒指編譯器的特性來確保常量的正確。