一研侣、const 的介紹和基本使用以及使用場(chǎng)景
1.1、const 簡(jiǎn)介:經(jīng)常使用的字符串常量炮捧,一般是抽成宏庶诡,但是蘋果不推薦我們抽成宏,推薦我們使用const常量咆课。
-
1.2末誓、const 作用:限制類型
- const 僅僅用來修飾右邊的變量(基本數(shù)據(jù)變量p,指針變量
*p
)书蚪,被const修飾的變量是只讀的喇澡。如下-
const 用法一 (修飾基本變量p)
不使用const修飾基本變量,允許修改值int a = 10; a = 12; NSLog(@"a=%d",a); 打印結(jié)果:a=12
使用const修飾基本變量
//這兩種寫法是一樣的殊校,const只修飾右邊的基本變量 b const int b = 5; // b:只讀變量 int const b = 5; // b:只讀變量 // 由于b是只讀的晴玖,b無法被修改,入下代碼會(huì)報(bào)錯(cuò) b = 3 // 報(bào)錯(cuò)为流,b無法修改
-
const 用法二 (修飾指針變量
*p
呕屎,帶*
的變量,就是 指針變量)
不使用const修飾指針變量// 修飾指針變量 *p敬察,帶 * 的變量秀睛,就是指針變量 // 定義一個(gè)指向int類型的指針變量,指向a的地址 a = 12; int *p = &a; int c = 7; p = &c; NSLog(@"p=%d",*p); 打印結(jié)果:p=7 // 由于 p 沒有被修飾莲祸,它訪問 內(nèi)存空間的值 和 指向的地址 都可以被修改允許修改 *p = 11; NSLog(@"p=%d",p); 打印結(jié)果:p=11
使用
const
修飾指針變量蹂安,const
修飾指針變量訪問的內(nèi)存空間,修飾的是右邊東西,如下 8 種情況來分析// 1虫给、2藤抡、4 的效果一樣 都是修飾 const右邊的 *q侠碧,3修飾的是變量 q ,切記 const修飾的是右邊的 int const *q = 7; // 1 const int *q = 7; // 2 int * const q = 7; // 3 const int *q = 7; // 4 // 首先下面的 q 都被修飾抹估,也就是q不能被賦值,然后 * const q 又被 const 修飾 int const * const q = 7; // 5 const int * const q = 7; // 6 const int * const q = 7; // 7 const int * const q = 7; // 8
提示:
-
1弄兜、2药蜻、4
的效果一樣 都是修飾 const右邊的*q
,3
修飾的是變量q
,切記const
修飾的是右邊的 - 首先下面的
q
都被修飾替饿,也就是q
不能被賦值语泽,然后* const q
又被const
修飾
-
-
- const 僅僅用來修飾右邊的變量(基本數(shù)據(jù)變量p,指針變量
-
1.3、const 的使用場(chǎng)景(場(chǎng)景一用的居多)
-
場(chǎng)景一:修飾全局變量视卢,目的是:使外界無法修改變量踱卵,保持只讀,提高預(yù)編譯的速度和時(shí)間(蘋果建議使用 const),如下:
// 設(shè)置基礎(chǔ)的url,這樣來保證base_url的不變(封裝請(qǐng)求的類) NSString * const base_url = @"http://www.baodu.com/";
-
場(chǎng)景二:修飾方法中的參數(shù)惋砂,如下
-(void)constTest2{ [self test:@"你好妒挎!"]; int p = 1; [self test1:&p]; [self test2:2]; } // 當(dāng)一個(gè)方法的參數(shù),只讀. -(void)test:(NSString * const)string{ // 這句代碼是報(bào)錯(cuò)的西饵,被 const 修飾過后酝掩,string 是無法被修改的 string = @"234"; } // 指針只讀,不能通過指針修改值 - (void)test1:(int const *)a{ // *a = 11; } // 基本數(shù)據(jù)類型只讀 - (void)test2:(int const)a{ }
-
二、宏 的簡(jiǎn)單使用
2.1眷柔、基本概念:宏是一種批量處理的稱謂期虾。一般說來,宏是一種規(guī)則或模式驯嘱,或稱語法替換 镶苞,用于說明某一特定輸入(通常是字符串)如何根據(jù)預(yù)定義的規(guī)則轉(zhuǎn)換成對(duì)應(yīng)的輸出(通常也是字符串)。這種替換在預(yù)編譯時(shí)進(jìn)行宙拉,稱作宏展開宾尚。編譯器會(huì)在編譯前掃描代碼,如果遇到我們已經(jīng)定義好的宏那么就會(huì)進(jìn)行代碼替換谢澈,宏只會(huì)在內(nèi)存中copy一份煌贴,然后全局替換,宏一般分為對(duì)象宏和函數(shù)宏,推薦博客锥忿。
2.2牛郑、宏的弊端:如果代碼中大量的使用宏會(huì)使預(yù)編譯時(shí)間變長(zhǎng)。
-
2.3敬鬓、常用宏舉例如下
/** 1淹朋、屏幕的寬高 */ #define JK_SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width #define JK_SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height /** 2、判斷是不是蘋果手機(jī) */ #define JKIs_Iphone (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
-
2.4钉答、const與宏的區(qū)別础芍?
答:1.編譯時(shí)刻 宏:預(yù)編譯 const:編譯;2.編譯檢查 宏沒有編譯檢查数尿,const有編譯檢查仑性;3.宏的好處 定義函數(shù),方法 const不可以右蹦;4.宏的壞處 大量使用宏诊杆,會(huì)導(dǎo)致預(yù)編譯時(shí)間過長(zhǎng)
提示:
- 預(yù)編譯:在打開項(xiàng)目的時(shí)候上面會(huì)有一個(gè)加載項(xiàng)目的進(jìn)度條就是預(yù)編譯
- 編譯:command+R和command+B都是編譯
- 網(wǎng)上的誤區(qū):大量使用宏,會(huì)導(dǎo)致內(nèi)存暴增(定義一個(gè)字符串的宏何陆,賦值給多個(gè)變量晨汹,打印其內(nèi)存地址,經(jīng)過測(cè)試:宏定義的是常量贷盲,常量都放在常量區(qū)淘这,只會(huì)生成一份內(nèi)存,故網(wǎng)上說的都是不對(duì)的),如下圖
三、static 簡(jiǎn)單使用
-
3.1铝穷、修飾局部變量
-
<1>朦乏、被static修飾局部變量,延長(zhǎng)生命周期氧骤,跟整個(gè)應(yīng)用程序有關(guān)呻疹,程序結(jié)束才會(huì)銷毀,如下:在一個(gè)類的里面打印下面的方法筹陵,只要程序不銷毀,
a
的值就不會(huì)被銷毀刽锤,會(huì)一直保持最后一次給a
賦的值-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ static int a = 0; ++a; NSLog(@"a=%d",a); }
-
<2>、被
static
修飾局部變量朦佩,只會(huì)分配一次內(nèi)存,如下:從打印結(jié)果我們可以看到并思,a
的內(nèi)存地址不會(huì)再變static int a = 0; ++a; NSLog(@"a = %d a的內(nèi)存地址=%p",a,&a); 部分打印結(jié)果: a = 1 a的內(nèi)存地址=0x10e758160 a = 2 a的內(nèi)存地址=0x10e758160 a = 3 a的內(nèi)存地址=0x10e758160 a = 4 a的內(nèi)存地址=0x10e758160
提示:被static修飾局部變量什么時(shí)候分配內(nèi)存?程序一運(yùn)行就會(huì)給static修飾變量分配內(nèi)存
-
-
3.2语稠、修飾全局變量宋彼,被static修飾全局變量,作用域會(huì)修改仙畦,也就是只能在當(dāng)前文件下使用
#import "ViewController.h" static int b = 20; @interface ViewController () @end @implementation TestViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor purpleColor];; } @end
四输涕、extern 簡(jiǎn)單使用
-
4.1、聲明外部全局變量(只能用于聲明慨畸,不能用于定義)莱坎,舉例如下:我們?cè)陬惱锩娑x的全局變量,在其他的類里面使用的時(shí)候只要聲明一下就好
#import "ViewController.h" int x = 20; @interface ViewController () @end @implementation TestViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor purpleColor];; } @end
在其他類里面使用一寸士,如下:聲明一下即可
#import "TestViewController.h" @interface TestViewController () @end @implementation TestViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor purpleColor];; } extern int x; -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ NSLog(@"x的值是:%d",x); // 打印結(jié)果: x的值是:20 } @end
在其他類里面使用二檐什,如下:在
ViewController
類的.h
里面聲明一下即可,如下:#import <UIKit/UIKit.h> @interface ViewController : UIViewController extern int x; @end
4.2弱卡、extern工作原理:先會(huì)去當(dāng)前文件下查找有沒有對(duì)應(yīng)全局變量乃正,如果沒有,才會(huì)去其他文件查找
五婶博、static 與 const 聯(lián)合使用
5.1瓮具、回顧一下 static 與 const
const:修飾全局變量
static:修飾全局變量,修改作用域-
5.2凡蜻、static 與 const 聯(lián)合使用
如果我們想這個(gè)BASE_URL
無法被其他類使用搭综,那么我們就在前面加上static
因?yàn)?static 修飾全局變量垢箕,修改作用域划栓,只能在UrlTest
里面使用,再其他類里面使用是不可以的,切記:這個(gè)BASE_URL
是在.m
里面定義的#import "UrlTest.h" static NSString * const BASE_URL = @"http://www.baodu.com/"; @implementation UrlTest @end
六条获、extern 與 const 聯(lián)合使用
-
6.1忠荞、開發(fā)中使用場(chǎng)景:在多個(gè)文件中經(jīng)常使用的同一個(gè)字符串常量,可以使用extern與const組合。原因入下:
- static與const組合:在每個(gè)文件都需要定義一份靜態(tài)全局變量委煤。
- extern與const組合:只需要定義一份全局變量堂油,多個(gè)文件共享。
提示:開發(fā)中便于管理所有的全局變量碧绞,通常搞一個(gè)Global文件府框,里面專門定義全局變量,統(tǒng)一管理讥邻,要不然項(xiàng)目文件太多不好找迫靖。
-
6.2、extern的基本使用 :當(dāng)我們?cè)谝粋€(gè)防止一個(gè)變量被修改的時(shí)候兴使,我們?cè)谇懊婕由?
const
,如下,僅僅是BASE_URL
無法被修改系宜,在自己的.h
文件里面extern
聲明一下即可,在其他類里面通過 導(dǎo)入.h
文件发魄,還是可以使用的BASE_URL
的-
UrlTest的.h文件 ( 聲明
BASE_URL
)#import "UrlTest.h" // 聲明 BASE_URL extern NSString * const BASE_URL; @implementation UrlTest @end
-
UrlTest的.m文件
#import "UrlTest.h" NSString * const BASE_URL = @"http://www.baodu.com/"; @implementation UrlTest @end
提示:定義全局的東西盹牧,遵循規(guī)定,頂一個(gè)以全局的文件來管理全局變量励幼,以避免全局變量重復(fù)定義
-
-
6.3汰寓、extern 的高級(jí)使用 (模仿
YYKIT
的使用 ),其實(shí)它只是把蘋果的宏拿過來改改名字,看起來很牛逼苹粟,我們也可以牛逼一下踩寇,如下:-
蘋果的定義:
#ifdef __cplusplus #define UIKIT_EXTERN extern "C" __attribute__((visibility ("default"))) #else #define UIKIT_EXTERN extern __attribute__((visibility ("default"))) #endif
-
我們只需要把
UIKIT_EXTERN
改為JKKIT_EXTERN
,那以后我們就可以使用我們自己定義的#ifdef __cplusplus #define JKKIT_EXTERN extern "C" __attribute__((visibility ("default"))) #else #define JKKIT_EXTERN extern __attribute__((visibility ("default"))) #endif
-
蘋果和我們自己定義的使用如下
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #ifdef __cplusplus #define JKKIT_EXTERN extern "C" __attribute__((visibility ("default"))) #else #define JKKIT_EXTERN extern __attribute__((visibility ("default"))) #endif // 使用自己定義的 JKKIT_EXTERN NSString * const BASE_URL; // 使用蘋果定義的 UIKIT_EXTERN // UIKIT_EXTERN NSString * const BASE_URL; NS_ASSUME_NONNULL_BEGIN @interface UrlTest : NSObject @end NS_ASSUME_NONNULL_END
-