引用[Effectuve Objective-C] static 修飾則意味着該變量僅在定義此變量的編譯單元中可見, 不會致使其餘單元重複致使命名衝突, 當編譯器編譯到此單元時, 就會輸出一份 "目標文件"(object file)bash
其可用於修飾常量變量或函數, 延長其生命週期, 被修飾的數據類型會保存到 bbs段(靜態區) 中, 內存由編譯器分配, 通常隨程序結束後清除釋放, 被修飾的數據類型, 系統只會爲其分配一次內存地址, 因此用於修飾數據類型時, 無論執行多少次, 被修飾的數據類型只會初始化一次。框架
static NSTimeInterval kAnimationDuration = 0.3;
@implementation JSDAnimationVC
複製代碼
在全局變量前加static, 全局變量就被定義成爲一個全局靜態變量(全局變量和靜態全局變量的生命週期是同樣的, 都是在堆中的靜態區, 在整個工程執行期間內一直存在) 而靜態全局變量則限制了其做用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。函數
特色以下:學習
相對全局變量優勢:優化
做用域只在原文件內, 不會影響到其餘文件, 同理也不受其餘文件影響。 避免其餘文件重定義致使命名衝突。動畫
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
for (NSInteger i = 0; i < 100; i++) {
static int count = 10;
count++;
};
}
複製代碼
與修飾變量做用同理。spa
const 表示常量, 被修飾以後的數據類型, 由變量轉爲常量, 其不能夠被修改, 在編譯階段會執行檢查, 其存儲區域位於常量區, 經常使用於配合 static 或 extern 使用。翻譯
static const NSTimeInterval kAnimationDuration = 0.3;
@implementation JSDAnimationVC
複製代碼
上面的全局變量表示的是動畫執行時間, 雖然其不會受外部文件影響, 可是在內部文件是能夠直接對其進行從新賦值的, 這明顯不符合咱們需求, 在變量前面加上關鍵字 const便可.指針
kAnimationDuration 全局靜態變量被修飾後變成全局靜態常量, 其內存區域由 bbs移動到常量區。code
用法:
extern NSString* const JSDLoginManagerDidLoginNotification;
@interface JSDLoginManagerVC : ViewController
@end
NSString * const JSDLoginManagerDidLoginNotification = @"JSDLoginManagerDidLoginNotification";
@implementation JSDCrashVC
複製代碼
包括在 .h .m 文件內聲明的變量, 都屬於全局變量, 除非 @implementation 做用域內聲明的, 因此這些全局變量都有可能由外部進行訪問, 並修改致使獲取不到意料的結果, 咱們可使用 const 來對其限制。 當外部文件訪問時須要使用關鍵字 extern 而且指明常量聲明的類型來使用, 不然編譯器默認以 int 類型來處理。應該是與運行時有關。
在**@implementation** 實現中, 方法實現內進行聲明 主要用於修飾 C 或 OC 數據類型, 使聲明的變量定義爲常量。 下面列舉下三種修飾寫法, 致使不一樣的結果。
const NSString * name = @"Jersey";
使 *name 指針地址不可變, 實際指向內容不受影響, 修改指針地址編譯器報錯。
NSString const * name = @"Jersey";
同上面寫法一致, 修飾了 name 指針地址使其不可變
NSString * const name = @"Jersey";
使 *name 指針指向內容不可變, 指針地址不受影響, 修改內容則編譯報錯。
複製代碼
總結: const 修飾其後面內容
這個單詞翻譯過來是"外面的, 外部的"。 顧名思義, 它的做用是聲明外部全局變量。這裏須要特別注意 extern 只能聲明, 不能用於實現。 當使用 extern 來聲明變量時, 其會先在編譯單元內部進行查找, 若是沒有則繼續到外部進行查找, 若是缺乏實現而且使用到了此數據時會致使編譯不經過。
用法:
最經常使用也是最多見的實現通常是, .h 用 extern 修飾可供外部使用, .m 實現
extern NSString* const JSDLoginManagerDidLoginNotification;
@interface JSDLoginManagerVC : ViewController
@end
NSString * const JSDLoginManagerDidLoginNotification = @"JSDLoginManagerDidLoginNotification";
@implementation JSDCrashVC
複製代碼
這種比較少見, 好比使用三方庫時, 三方庫定義了全局變量或常量, 可是並無在 .h 用 extern 修飾其聲明出來, 這時候若是咱們想要去使用時, 能夠直接在 .h 對其進行修飾便可直接使用
extern NSString* const JSDLoginManagerDidLoginNotification;
@interface JSDManager : NSObject
@end
複製代碼
主要配合關鍵字 const 使用, 相似用法一。
簡單說其實就是字符替換, 系統會在調用的地方進行文本替換, 可用於修飾數據, 函數, 結構體, 方法等, 系統不會對其作類型檢查。
引用喵神**[宏定義的黑魔法]**原文: 宏定義在C系開發中能夠說佔有舉足輕重的做用。底層框架自沒必要說,爲了編譯優化和方便,以及跨平臺能力,宏被大量使用,能夠說底層開發離開define將步履維艱。而在更高層級進行開發時,咱們會將更多的重心放在業務邏輯上,彷佛對宏的使用和依賴並很少。可是使用宏定義的好處是不言自明的,在節省工做量的同時,代碼可讀性大大增長。若是想成爲一個能寫出漂亮優雅代碼的開發者,宏定義絕對是必不可少的技能
得益於宏定義的高效與靈活性, 在不少底層系統中大量被使用, 其玩法也很是的多, 感興趣的能夠參考喵神這篇文章
宏定義是在預編譯期間處理, 在使用時系統直接進行的方法替換, 靜態變量等則是在編譯期間進行的。 宏定義不會系統不會作編譯檢查, 因此類型錯誤也能經過編譯, const 則會作編譯檢查。 能顯式的聲明數據類型, 而且不會出現本身定義的宏被其餘人員更換,致使出現難以排查的 Bug。 不過宏不只能對數據類型進行定義, 還能對函數, 結構體, 方法等進行定義相對比起常量來講做用會更多一些。
總結
建議: 在實際開發中, 對於能使用常量定義完成的, 儘可能使用常量能實現, 而不要考慮使用 宏。 讀 [Effective Objective-C] 第四條: 多用類型常量, 少用 #define 與處理指令, 蘋果也推薦咱們在開發中儘可能使用常量。
但願此篇文章對您有所幫助,若有不對的地方,但願你們能留言指出糾正。謝謝!!!!! 學習的路上,與君共勉!!!
參考