網(wǎng)站首頁 編程語言 正文
正文
在編寫代碼時(shí)經(jīng)常要使用常量,來替代 magic number。比較簡單的做法是通過預(yù)處理指令 #define
來實(shí)現(xiàn)。
#define ANIMATION_DURATION 0.3
上述預(yù)處理指令會(huì)在編譯時(shí)的預(yù)處理階段會(huì)將代碼中 ANIMATION_DURATION
字符串替換為 0.3
。這種定義常量的方式比較簡便,但是存在兩個(gè)問題:
- 丟失了類型信息。
- 若該預(yù)處理指令聲明在頭文件中,引入該頭文件的代碼,
ANIMATION_DURATION
都會(huì)被替換,可能出現(xiàn)沖突。
Objective-C 的常量聲明方式
幸運(yùn)的是,Objective-C
中提供了 const
關(guān)鍵字,可以用來定義常量。const
關(guān)鍵字可以對(duì)變量加以限定,使其值不能被改變,在整個(gè)作用域中都保持固定。
const NSTimeInterval kAnimationDuration = 0.3;
這種方式定義的常量包含類型信息,且在編譯時(shí)即可檢查是否與其他常量出現(xiàn)沖突。如果試圖修改由 const
修飾符所聲明的變量,那么編譯器就會(huì)報(bào)錯(cuò)。
如果常量僅在某個(gè)實(shí)現(xiàn)文件中使用,還應(yīng)該加上 static
關(guān)鍵字,否則會(huì)被視為全局常量。若不使用 static
,編譯器會(huì)為它創(chuàng)建一個(gè)外部符號(hào),若另一個(gè)編譯單元中也聲明了同名變量,就會(huì)報(bào)錯(cuò)。
static const NSTimeInterval kAnimationDuration = 0.3;
當(dāng)一個(gè)變量同時(shí)使用了 static
和 const
,那么編譯器并不會(huì)創(chuàng)建符號(hào),而是會(huì)像 #define
預(yù)處理指令一樣,把所有遇到的變量替換為常值。
有時(shí)候需要把一個(gè)常量暴露給外界使用,比如通知,此類常量需放在全局符號(hào)表中。可以使用 extern
關(guān)鍵字,在頭文件中進(jìn)行聲明:
// .h extern NSString * const AFNetworkingTaskDidResumeNotification; // .m NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";
該常量在頭文件中聲明,在實(shí)現(xiàn)文件中定義。需要注意的是 const
寫在指針類型的右邊意味著該指針的指向不可被改變,若寫在左邊意味著該指針指向的內(nèi)容不可被改變。
按上述方式實(shí)現(xiàn)并定義后,在編譯時(shí)生成目標(biāo)文件時(shí),編譯器會(huì)在數(shù)據(jù)段為字符串分配存儲(chǔ)空間。
在 Foundation
框架中,蘋果為了兼容 C++
中對(duì) extern
的使用,提供了宏:
#if defined(__cplusplus) #define FOUNDATION_EXTERN extern "C" #else #define FOUNDATION_EXTERN extern #endif #define FOUNDATION_EXPORT FOUNDATION_EXTERN #define FOUNDATION_IMPORT FOUNDATION_EXTERN
一個(gè) C++
程序中可能包含其他語言編寫的部分代碼,同樣,C++
編寫的代碼片段也可能被用在其他語言編寫的代碼中。但是,不同語言編寫的代碼相互調(diào)用是困難的,更何況用同一種語言編寫,使用不同編譯器進(jìn)行編譯的情況。因?yàn)椋煌Z言或者同種語言在不同編譯器上編譯時(shí),在注冊(cè)變量,傳遞參數(shù)和參數(shù)在棧上的布局上可能存在差異。
為了使它們遵守統(tǒng)一規(guī)則,可以使用 extern
指定一個(gè)編譯和鏈接規(guī)約。extern "C"
指令中的 C
,表示的是一種編譯和鏈接規(guī)約,而不是一種語言。C
表示符合 C
語言的編譯和鏈接規(guī)約的任何語言。
還要說明的是,extern "C"
指令指定的編譯和鏈接規(guī)約,不會(huì)影響語義,只是改變編譯和鏈接的方式。
而 FOUNDATION_EXPORT
和 FOUNDATION_IMPORT
是用來兼容 Win32
應(yīng)用程序的,移動(dòng)端開發(fā)可以忽略。
所以上述對(duì)全局常量的聲明,可以寫成:
// .h FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification; // .m NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";
在 Objective-C 中使用 let 來聲明常量
使用過 Swift
的同學(xué),一定對(duì)其聲明常量的方式的簡潔性印象深刻,在 Swift
中聲明常量的方式如下所示:
let kAnimationDuration = 0.3
之所以能如此簡潔,是因?yàn)?Swift
具有 let
關(guān)鍵字和類型推斷的能力,但其實(shí)在 Objective-C
中也可以通過類似的方式來書寫常量。
Objective-C
中有一個(gè)關(guān)鍵字,是 __auto_type
,可以實(shí)現(xiàn)類似 Swift
中類型推斷能力的關(guān)鍵字,如下所示:
const __auto_type kAnimationDuration = 0.3;
可能對(duì)于簡單的數(shù)據(jù)類型,這樣的優(yōu)勢(shì)不是很明顯,但是對(duì)于具有復(fù)雜泛型的類型來說,可以說優(yōu)勢(shì)很大了:
// 舊方式 NSArray<NSDictionary<NSString *, NSString *> *> *models = ...; // 新方式 __auto_type models = ...;
同時(shí),可以通過宏的方式,來減少 __auto_type
的書寫,即可實(shí)現(xiàn)通過 let
聲明常量,var
聲明變量。其中 auto 關(guān)鍵字是為了兼容 C++。
#if defined(__cplusplus) #define let auto const #else #define let const __auto_type #endif #if defined(__cplusplus) #define var auto #else #define var __auto_type #endif
聲明了上面的宏之后,就可以直接使用了:
let kAnimationDuration = 0.3;
原文鏈接:https://juejin.cn/post/7089744654685929503
相關(guān)推薦
- 2023-02-23 Android中URLEncoder空格被轉(zhuǎn)碼為"+"號(hào)的處理辦法_Android
- 2022-09-25 MyBatis實(shí)現(xiàn)多表查詢(一對(duì)一、一對(duì)多)的方式
- 2022-07-20 初識(shí)C語言習(xí)題以及知識(shí)點(diǎn)
- 2022-02-14 taro將頁面滾動(dòng)到指定位置
- 2022-04-26 jQuery實(shí)現(xiàn)表格的數(shù)據(jù)拖拽_jquery
- 2022-07-22 使用@ControllerAdvice和@ExceptionHandler構(gòu)建全局異常處理器
- 2023-01-14 Go?庫bytes.Buffer和strings.Builder使用及性能對(duì)比_Golang
- 2023-05-22 python中decimal模塊的用法_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支