iOS開發中很重要,很常用,但卻容易被忽略的知識點:id ,NSObject, id區別

來源:互聯網
上載者:User

我們經常會混淆以下三種申明(我是沒有留意過):

  • 1. id foo1;
  • 2. NSObject *foo2;
  • 3. id<NSObject> foo3;

        第一種是最常用,它簡單地申明了指向對象的指標,沒有給編譯器任何類型資訊,因此,編譯器不會做類型檢查。但也因為是這樣,你可以發送任何資訊給id類型的對象。這就是為什麼+alloc返回id類型,但調用[[Foo alloc] init]不會產生編譯錯誤。

        因此,id類型是運行時的動態類型,編譯器無法知道它的真實類型,即使你發送一個id類型沒有的方法,也不會產生編譯警告。

        我們知道,id類型是一個Objective-C對象,但並不是都指向繼承自NSOjbect的對象,即使這個類型和NSObject對象有很多共同的方法,像retain和release。要讓編譯器知道這個類繼承自NSObject,一種解決辦法就是像第2種那樣,使用NSObject靜態類型,當你發送NSObject沒有的方法,像length或者count時,編譯器就會給出警告。這也意味著,你可以安全地使用像retain,release,description這些方法。

        因此,申明一個通用的NSObject對象指標和你在其它語言裡做的類似,像java,但其它語言有一定的限制,沒有像Objective-C這樣靈活。並不是所有的Foundation/Cocoa對象都繼承息NSObject,比如NSProxy就不從NSObject繼承,所以你無法使用NSObject*指向這個對象,即使NSProxy對象有release和retain這樣的通用方法。為瞭解決這個問題,這時候,你就需要一個指向擁有NSObject方法對象的指標,這就是第3種申明的使用情景。

        id<NSObject>告訴編譯器,你不關心對象是什麼類型,但它必須遵守NSObject協議(protocol),編譯器就能保證所有賦值給id<NSObject>類型的對象都遵守NSObject協議(protocol)。這樣的指標可以指向任何NSObject對象,因為NSObject對象遵守NSObject協議(protocol),而且,它也可以用來儲存NSProxy對象,因為它也遵守NSObject協議(protocol)。這是非常強大,方便且靈活,你不用關心對象是什麼類型,而只關心它實現了哪些方法。

         現在你知道你要用什麼類型了不?

         如果你不需要任何的類型檢查,使用id,它經常作為傳回型別,也經常用於申明代理(delegate)類型。因為代理類型通常在運行時,才會檢查是否實現了那些方法。

        如果真的需要編譯器檢查,那你就考慮使用第2種或者第3種。很少看到NSObject*能正常運行,但id<NSObject>無法正常啟動並執行。使用協議(protocol)的優點是,它能指向NSProxy對象,而更常用的情況是,你只想知道某個對象遵守了哪個協議,而不用關心它是什麼類型。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.