宏的常見(jiàn)用法:
- 常見(jiàn)字符串抽成宏
- 常見(jiàn)代碼抽成宏
const(常量)
當(dāng)有字符串常量的時(shí)候,蘋(píng)果推薦我們使用const,蘋(píng)果經(jīng)常把常用字符串定義成const
宏與const的區(qū)別
編譯時(shí)刻
:宏是預(yù)編譯(編譯之前處理),const是編譯階段。編譯檢查
:宏不做檢查,不會(huì)報(bào)編譯錯(cuò)誤,只是替換,const會(huì)編譯檢查,會(huì)報(bào)編譯錯(cuò)誤。宏的好處
:宏能定義一些函數(shù),方法。 const不能。-
宏的壞處
:使用大量宏,容易造成編譯時(shí)間久,每次都需要重新替換。注意:很多Blog都說(shuō)使用宏,會(huì)消耗很多內(nèi)存,但是并不會(huì)生成很多內(nèi)存,宏定義的是常量,常量都放在常量區(qū),只會(huì)生成一份內(nèi)存。
const
- 1.const僅僅用來(lái)修飾右邊的變量(基本數(shù)據(jù)變量p,指針變量*p,對(duì)象變量)
- 2.被const修飾的變量是只讀的。
const的簡(jiǎn)單使用
首先我們要復(fù)習(xí)一下C語(yǔ)言的指針
// 定義int變量
int a = 66;
int b = 88;
// 定義指向a的指針變量
int *p=&a;
// 修改p的地址
p = &b;
*p = 30;
NSLog(@"%d",b);
請(qǐng)問(wèn)打印值為多少?
首先p是指向a的指針,p保存的是a的地址,p=&b時(shí),p變成的指向b的指針,所以*p=30,其實(shí)就是給b附值,所以打印結(jié)果為30。
寫(xiě)下來(lái)要使用const了
// 用const修飾指針變量
int * const p = &a;
此時(shí)
(1) p=&b;
(2) *p=30;
請(qǐng)問(wèn)1和2哪個(gè)會(huì)報(bào)錯(cuò)?
上面解釋了const是修飾右邊的變量是只讀的,所以說(shuō) p是只讀的那么1就會(huì)報(bào)錯(cuò)。
const int * p = &a;
此時(shí)
(1) p=&b;
(2) *p=30;
請(qǐng)問(wèn)1和2哪個(gè)會(huì)報(bào)錯(cuò)?
同理 所以說(shuō) p是只讀的那么2就會(huì)報(bào)錯(cuò)。
其實(shí) const int * p = &a; 與 int const p = &a; 是等價(jià)的
有兩個(gè)更變態(tài)的寫(xiě)法
int const * const p = &a; // *p:只讀 p:只讀
const int * const p = &a; // *p:只讀 p:只讀
不用說(shuō)大家也理解了吧
現(xiàn)在大家明白了const的作用吧,點(diǎn)開(kāi)蘋(píng)果頭文件可以開(kāi)到很多這樣的寫(xiě)法,現(xiàn)在你是不是可以理解蘋(píng)果為什么要這樣做了嗎?
UIKIT_EXTERN NSString *const UIViewControllerHierarchyInconsistencyException NS_AVAILABLE_IOS(5_0);
那我們繼續(xù)學(xué)習(xí)const的用法吧
const開(kāi)發(fā)中使用場(chǎng)景:
- 1.當(dāng)一個(gè)方法參數(shù)只讀
- 2.定義只讀全局變量
很多時(shí)候我們?cè)陂_(kāi)發(fā)中都要static和extern與const聯(lián)合使用,所以接下來(lái)學(xué)習(xí)一下static和extern和的作用
static作用
修飾局部變量:
1.延長(zhǎng)局部變量的生命周期,程序結(jié)束才會(huì)銷毀。
2.局部變量只會(huì)生成一份內(nèi)存,只會(huì)初始化一次。修飾全局變量
1.只能在本文件中訪問(wèn),修改全局變量的作用域,生命周期不會(huì)改。
修飾局部變量
for (int i=0; i<10; i++) {
int a = 0;
a++;
NSLog(@"%d",a);
}
請(qǐng)問(wèn)輸出結(jié)果為多少?每次進(jìn)入大括號(hào)內(nèi)都會(huì)重新初始化 a 所以結(jié)果為 1。
如果加上static呢
for (int i=0; i<10; i++) {
static int a = 0;
a++;
NSLog(@"%d",a);
}
此時(shí)的請(qǐng)問(wèn)輸出結(jié)果為多少?
static:修飾的變量,程序一運(yùn)行就會(huì)分配一次內(nèi)存,用static修飾的代碼,只會(huì)在程序一啟動(dòng)就會(huì)執(zhí)行,以后就不會(huì)在執(zhí)行,所以結(jié)果為10。
extern作用:
聲明一個(gè)變量,不能定義變量
注意:extern修飾的變量不能初始化
使用場(chǎng)景,一般用于聲明全局變量
static與const聯(lián)合使用
static與const作用:聲明一個(gè)只讀的靜態(tài)變量
-
開(kāi)發(fā)使用場(chǎng)景:在
一個(gè)文件中
經(jīng)常使用的字符串常量,可以使用static與const組合static NSString * const key = @"name";
所以大家要記住:staic和const聯(lián)合的作用:聲明一個(gè)在本文件中靜態(tài)的全局只讀常量**
iOS中staic和const常用使用場(chǎng)景,是用來(lái)代替宏,把一個(gè)經(jīng)常使用的字符串常量,定義成靜態(tài)全局只讀變量。
extern與const聯(lián)合使用
開(kāi)發(fā)中使用場(chǎng)景:在多個(gè)文件中
經(jīng)常使用的同一個(gè)字符串常量,可以使用extern與const組合。
- 原因:
- static與const組合:在每個(gè)文件都需要定義一份靜態(tài)全局變量。
- extern與const組合:只需要定義一份全局變量,多個(gè)文件共享。
- 全局常量正規(guī)寫(xiě)法:開(kāi)發(fā)中便于管理所有的全局變量,通常搞一個(gè)全局的文件,里面專門定義全局變量,統(tǒng)一管理,要不然項(xiàng)目文件多不好找。
比如我們?cè)谛陆ㄒ粋€(gè)文件,只留.m里#import <Foundation/Foundation.h>,其他的都刪除了
在.m里定義
NSString * const name = @"zhanming";
NSString * const name1 = @"zhanming";
NSString * const name2 = @"zhanming";
NSString * const name3 = @"zhanming";
在.h里引用
extern NSString * const name ;
extern NSString * const name1 ;
extern NSString * const name2 ;
extern NSString * const name3 ;
這樣就可以在程序里引用了哈哈,可是我們點(diǎn)開(kāi)蘋(píng)果的頭文件發(fā)現(xiàn)
UIKIT_EXTERN NSString *const UIViewControllerShowDetailTargetDidChangeNotification NS_AVAILABLE_IOS(8_0);
蘋(píng)果用了UIKIT_EXTERN
這是什么的不要擔(dān)心我們點(diǎn)進(jìn)去看看發(fā)現(xiàn)
#define UIKIT_EXTERN extern __attribute__((visibility ("default")))
居然就是extern
把我們的在.h里extern換成UIKIT_EXTERN
UIKIT_EXTERN NSString * const name ;
UIKIT_EXTERN NSString * const name1 ;
UIKIT_EXTERN NSString * const name2 ;
UIKIT_EXTERN NSString * const name3 ;
現(xiàn)在是不是覺(jué)得高大上了呢?
最后提醒:在iOS開(kāi)發(fā)中請(qǐng)盡量多使用const、enum來(lái)代替宏定義(#define),隨著項(xiàng)目工程的逐漸增大,過(guò)多的宏定義還可能影響項(xiàng)目的編譯速度.
如果感覺(jué)這篇文章對(duì)您有所幫助,順手點(diǎn)個(gè)喜歡,謝謝啦