在 iOS 專案中,我們習慣在 Prefix Header (.pch) 文件中定義全局常用的字符串、數值等。早期開發者多用 #define 宏定義,但細研 Apple 官方框架會發現,其大量使用 const 修飾常量。本文深入剖析 const 與宏的本質區別,並給出工程級的最佳實踐方案。
const int age1 = 20;
int const age2 = 30; // 效果相同,均為只讀常量
int age = 20;
const int *p1 = &age; // *p1 為常量,不可通過 p1 修改值
int const *p2 = &age; // 同上
int * const p3 = &age; // p3 本身為常量,不可指向其他地址
// *p3 = 30; // 正確:可修改指向內容
// p3 = # // 錯誤:p3 不可重新賦值
而非直接在 .pch 中堆砌宏,建議創建專門的常量頭文件與實現文件:
#import <Foundation/Foundation.h>
// 通知名稱常量
extern NSString * const ZYEmotionDidSelectNotification;
extern NSString * const ZYSelectEmotionKey;
extern NSString * const ZYEmotionDidDeleteNotification;
#import "ZYConst.h"
NSString * const ZYEmotionDidSelectNotification = @"ZYEmotionDidSelectNotification";
NSString * const ZYSelectEmotionKey = @"ZYSelectEmotionKey";
NSString * const ZYEmotionDidDeleteNotification = @"ZYEmotionDidDeleteNotification";
#import "ZYConst.h"
const 修飾的全局字符串在內存中只有一份拷貝,無論被多少文件引用,地址相同。宏定義在預處理階段會被展開,每次使用可能產生新的字符串字面量,造成內存浪費。const 變量擁有明確類型,編譯器可進行類型檢查;宏只是文本替換,無類型信息,易引發隱蔽錯誤。const 變量值;宏在預處理後消失,調試時不可見。const 遵循 C 語言作用域規則,可用 static 限制文件內可見;宏無作用域,全局污染風險高。涉及編譯時計算或參數化代碼片段時,const 無法替代:
// RGB 色值宏(需計算)
#define ZYColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
// 隨機顏色宏(含函數調用)
#define ZYRandomColor ZYColor(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256))
const 要求初始值為編譯期常量表達式,不支持運行時計算或函數調用,此類場景必須用宏。
「能用 const 就不用 #define」是現代 iOS 開發的鐵律。建立常量管理類,統一維護通知名、鍵值、配置參數,配合 .pch 引入,兼顧性能、可維護性與代碼規範。