編寫高品質的OC代碼--------熟悉Objective-C

來源:互聯網
上載者:User
    第1條:瞭解Objective-C語言的起源
        1、Objective-C的訊息結構
    Objective-C使用“訊息結構”而非“函數調用”。訊息結構與函數調用的關鍵區別在於:使用訊息結構的語言,其運行時所應執行的代碼由運行環境來決定;而使用函數調用的語言,由編譯器決定。如果函數調用是多態的,那麼在運行時就要按照“虛方法表”來查出到底應該執行哪個函數實現。而採用訊息結構的語言,不論是否多態,總是在運行時才會去查所要執行的方法。實際上,編譯器甚至不關心接收訊息的對象是何種類型。接收訊息的對象問題也要在運行時處理,其過程叫做“動態綁定”。
        2、Objective-C的執行階段程式庫
    Objective-C的重要工作都由“執行階段程式庫”而非編譯器完成的。執行階段程式庫提供了Objective-C的物件導向的能力,使用Objective-C的物件導向特性所需的全部資料結構及函數都是由“執行階段程式庫”提供的。舉例來說,運行期組件中含有全部記憶體管理方法。
        3、Objective-C的記憶體模型
      Objective-C中的對象是以指標來指示的。想要聲明一個變數,令其指代某個對象,可用以下文法:         NSString * someStr = @“The string”;       這種文法基本上是照搬C語言的,它聲明了一個名為someString的變數,其類型是NSString*。也就是說,此變數為指向NSString的指標。所有Objective-C語言的對象都必須這樣聲明,因為對象所佔記憶體總是分配在“堆空間”中,而絕不會分配在“棧”上。不能在棧中分配Objective-C對象。           如下代碼:
        NSString * someStr = @“The string”;
        NSString * anothreStr = someStr;
        只有一個NSString執行個體,然而又兩個變數指向此執行個體。兩個變數都是NSString* 型,這說明當前“棧幀”裡分配了兩塊兒記憶體,每塊記憶體的大小都能容下一枚指標(在32位架構的電腦上是4位元組,64位電腦上是8位元組)。這兩塊兒記憶體裡的值都一樣,就是NSString執行個體的記憶體位址。
        分配在堆中的記憶體必須直接管理,而分配在棧上用於儲存變數的記憶體則會在其棧幀彈出時自動清理。
        Objective-C將對記憶體管理抽象了出來。不需要用malloc及free來分配或釋放記憶體。Objective-C運行時環境把這一部分工作抽象為一套記憶體管理架構,名叫“引用計數”。
        如果只是儲存int、float、double、char等非物件類型,那麼通常使用CGRect這種結構體就可以了。CGRect是C語言結構體。儲存在棧上。整個系統架構都在使用這種結構體,因為如果改用Objective-C對象來做的話,效能會受到影響。與建立結構體相比,建立對象還需要額外開銷,例如分配及是否堆記憶體等。

     第2條:在類的標頭檔中盡量少引用其他標頭檔     1.        將引入標頭檔的時機盡量延後,只在確有需要時才引入,這樣就可以減少類的使用者所需引入的標頭檔梳理。縮短編譯時間。
    2.        向前聲明可以解決兩個類循環參考的問題,當兩個類循環參考的時候。使用#import而不是#include雖然不會導致死迴圈,但卻意味著兩個類裡有一個無法被正確編譯。
    3.          有時候必須要在標頭檔中引用其他標頭檔。如果你寫的類繼承自某個超類,則必須引入定義那個超類的標頭檔。同理,如果要聲明你寫的類繼承自某個超類,那麼必須由完整的定義,且不能使用向前聲明。向前聲明只能告訴編譯器有某個協議,而此時編譯器卻要知道該協議中定義的方法。所以協議通常聲明在一個單獨的檔案中(代理協議除外,代理協議單獨聲明是沒有任何意義的)。
    第3條:多用字面量文法,少用與之等價的方法
    字面量文法實際上只是一種“糖衣文法”,其效果與常規文法等效但是開發人員用起來卻更加方便。“糖衣文法”可令程式更易讀,減少代碼出錯幾率。
        要點:
        1、應該使用字面量文法來建立字串、數值、數組、字典。與建立此類對象的常規方法相比,這麼做更加簡明扼要。         2、應該通過取下標操作來訪問數組下標或字典中的鍵所對應的元素。         3、用字面量文法建立數組或字典時,若值中有nil,則會拋出異常。因此,務必確保值裡不含nil。      
      字面量文法的局限性:
        1、所建立出的對象必須屬於Foundation架構。要想建立自訂子類執行個體,必須採用“非字面量文法”。
        2、字面量文法建立出來的字串、數組、字典對象都是不可變的。若想要可變版本的對象,則需賦值一份:
    NSMutableArray * mutable = [ @[@1 , @2 , @3 , @4] mutableCopy ];
    
      第4條:多用類型常量,少用#define預先處理指令
    以如下預先處理為例為例:
    #define ANIMATION_DURATION 0.3     1、預先處理指令不攜帶類型資訊,類型常量攜帶類型資訊。
    2、預先處理指令範圍不明確,假設該指令聲明在某個標頭檔中,那麼所有引入了這個標頭檔的代碼,其 ANIMATION_DURATION 都會被替換 。   3、即使有人重新定義了常量值,編譯器也不會產生警告,這將導致應用程式中的常量值不一致。

  在實現檔案中定義“只在編譯單元內可見的常量” static const NSTimeInterval kAnimationDuration = 0.3 ;
  變數一定要同時用static和const來聲明。const確保變數不可變,static則意味著該變數僅在定義此變數的編譯單元中可見。假如聲明此變數時不加static,則編譯器會為它建立一個“外部符號”。此時若是另一個編譯單元中也聲明了同名變數,那麼編譯器會報錯。實際上,若干一個變數即聲明為static,又聲明為const,那麼編譯器根本不會建立符號,而是會像#define預先處理指令一樣,把所有遇到的變數都替換為常值。不過還是要記住:用這種方式的常量帶有類型資訊。   有時需要對外公開某常量。此類常量需放在“全域符號表”中,以便可以在定義該常量的編譯單元之外使用。應該這樣來定義

//In the header file
extern NSString * const EOCStringConstant;

//In the implementation file
NSString *const EOCStringConstant =@"VALUE";
    這種常量要出現在全域符號表中,所以其名稱應加以區隔,通常用與之相關的類名做首碼。總之,勿使用預先處理指令定義常量,而應藉助編譯器來確保常量正確。
    
  第5條:枚舉的使用     C++11標準修訂了枚舉的某些特性。其中一項改動是:可以指明用何種“底層資料類型”來儲存枚舉類型的變數。這樣做的好處是,可以向前聲明枚舉變數了。若不指定底層資料類型,則無法向前聲明枚舉類型。因為編譯器不清楚底層資料類型的大小,所以在用的此枚舉類型時,也就不知道究竟該給該變數分配多少記憶體空間。
    如果把傳遞給某個方法的選項表示為枚舉類型,而多個選項又可同時使用,那麼就將各選項值定義為2的冪,以便通過按位或操作將其組合起來。
    用NS_ENUM與NS_OPTIONS宏來定義枚舉類型,並指明其底層資料類型。這樣做可以確保枚舉是用開發人員所選的底層資料類型實現出來的,而不會採用編譯器所選的類型。
    在處理枚舉類型的switch語句中不要實現default分支。這樣的話,加入新枚舉之後,編譯器就會提示開發人員:switch語言並未處理所有枚舉

   

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.