1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        論如何在 Objective-C 中優(yōu)雅的使用常量

        共 3616字,需瀏覽 8分鐘

         ·

        2022-06-19 14:14

        ????關(guān)注后回復(fù) “進群” ,拉你進程序員交流群????

        在編寫代碼時經(jīng)常要使用常量,來替代 magic number。比較簡單的做法是通過預(yù)處理指令 #define 來實現(xiàn)。

        #define ANIMATION_DURATION 0.3 

        上述預(yù)處理指令會在編譯時的預(yù)處理階段會將代碼中 ANIMATION_DURATION 字符串替換為 0.3。這種定義常量的方式比較簡便,但是存在兩個問題:

        1. 丟失了類型信息。
        2. 若該預(yù)處理指令聲明在頭文件中,引入該頭文件的代碼,ANIMATION_DURATION 都會被替換,可能出現(xiàn)沖突。

        Objective-C 的常量聲明方式

        幸運的是,Objective-C 中提供了 const 關(guān)鍵字,可以用來定義常量。const 關(guān)鍵字可以對變量加以限定,使其值不能被改變,在整個作用域中都保持固定。

        const NSTimeInterval kAnimationDuration = 0.3;

        這種方式定義的常量包含類型信息,且在編譯時即可檢查是否與其他常量出現(xiàn)沖突。如果試圖修改由 const 修飾符所聲明的變量,那么編譯器就會報錯。

        如果常量僅在某個實現(xiàn)文件中使用,還應(yīng)該加上 static 關(guān)鍵字,否則會被視為全局常量。若不使用 static,編譯器會為它創(chuàng)建一個外部符號,若另一個編譯單元中也聲明了同名變量,就會報錯。

        static const NSTimeInterval kAnimationDuration = 0.3;

        當(dāng)一個變量同時使用了 staticconst,那么編譯器并不會創(chuàng)建符號,而是會像 #define 預(yù)處理指令一樣,把所有遇到的變量替換為常值。

        有時候需要把一個常量暴露給外界使用,比如通知,此類常量需放在全局符號表中??梢允褂?extern 關(guān)鍵字,在頭文件中進行聲明:

        // .h
        extern NSString * const AFNetworkingTaskDidResumeNotification;
        // .m
        NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";

        該常量在頭文件中聲明,在實現(xiàn)文件中定義。需要注意的是 const 寫在指針類型的右邊意味著該指針的指向不可被改變,若寫在左邊意味著該指針指向的內(nèi)容不可被改變。

        按上述方式實現(xiàn)并定義后,在編譯時生成目標(biāo)文件時,編譯器會在數(shù)據(jù)段為字符串分配存儲空間。

        Foundation 框架中,蘋果為了兼容 C++ 中對 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

        一個 C++ 程序中可能包含其他語言編寫的部分代碼,同樣,C++ 編寫的代碼片段也可能被用在其他語言編寫的代碼中。但是,不同語言編寫的代碼相互調(diào)用是困難的,更何況用同一種語言編寫,使用不同編譯器進行編譯的情況。

        因為,不同語言或者同種語言在不同編譯器上編譯時,在注冊變量,傳遞參數(shù)和參數(shù)在棧上的布局上可能存在差異。

        為了使它們遵守統(tǒng)一規(guī)則,可以使用 extern 指定一個編譯和鏈接規(guī)約。extern "C" 指令中的 C,表示的是一種編譯和鏈接規(guī)約,而不是一種語言。C 表示符合 C 語言的編譯和鏈接規(guī)約的任何語言。

        還要說明的是,extern "C" 指令指定的編譯和鏈接規(guī)約,不會影響語義,只是改變編譯和鏈接的方式。

        FOUNDATION_EXPORTFOUNDATION_IMPORT 是用來兼容 Win32 應(yīng)用程序的,移動端開發(fā)可以忽略。

        所以上述對全局常量的聲明,可以寫成:

        // .h
        FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification;
        // .m
        NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";

        在 Objective-C 中使用 let 來聲明常量

        使用過 Swift 的同學(xué),一定對其聲明常量的方式的簡潔性印象深刻,在 Swift 中聲明常量的方式如下所示:

        let kAnimationDuration = 0.3

        之所以能如此簡潔,是因為 Swift 具有 let 關(guān)鍵字和類型推斷的能力,但其實在 Objective-C 中也可以通過類似的方式來書寫常量。

        Objective-C 中有一個關(guān)鍵字,是 __auto_type,可以實現(xiàn)類似 Swift 中類型推斷能力的關(guān)鍵字,如下所示:

        const __auto_type kAnimationDuration = 0.3;

        可能對于簡單的數(shù)據(jù)類型,這樣的優(yōu)勢不是很明顯,但是對于具有復(fù)雜泛型的類型來說,可以說優(yōu)勢很大了:

        // 舊方式
        NSArray<NSDictionary<NSString *, NSString *> *> *models = ...;
        // 新方式
        __auto_type models = ...;

        同時,可以通過宏的方式,來減少 __auto_type 的書寫,即可實現(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

        -End-
        最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!
        點擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取
        在看點這里好文分享給更多人↓↓
        瀏覽 46
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲成人无码在线免费观看 | 中国偷窥妇wc | 国产乱伦一级aa视频 | 91久久香蕉囯产熟女线看 | 欧美 在线 日韩 | 骚老师影院 | 国产精品一区二区三区在线 | 天啪天天天天射日天 | 五月丁香婷婷在线观看视频 | 馒头逼一线天 |