Objective-C學(xué)習(xí)總結(jié)三 Category

1卒落、什么是Category?

category是Objective-C 2.0之后添加的語言特性诗芜,別人口中的分類、類別其實都是指的category竣贪。category的主要作用是為已經(jīng)存在的類添加方法帚湘。除此之外玫荣,apple還推薦了category的另外兩個使用場景。

  • 可以把類的實現(xiàn)分開在幾個不同的文件里面大诸。這樣做有幾個顯而易見的好處捅厂。

  • 可以減少單個文件的體積

  • 可以把不同的功能組織到不同的category里

  • 可以由多個開發(fā)者共同完成一個類

  • 可以按需加載想要的category

  • 聲明私有方法

  • apple 的SDK中就大面積的使用了category這一特性。比如UIKit中的UIView资柔。apple把不同的功能API進(jìn)行了分類焙贷,這些分類包括UIViewGeometry、UIViewHierarchy建邓、UIViewRendering等盈厘。

2、category特點(diǎn)
  • category只能給某個已有的類擴(kuò)充方法官边,不能擴(kuò)充成員變量沸手。

  • category中也可以添加屬性外遇,只不過@property只會生成setter和getter的聲明,不會生成setter和getter的實現(xiàn)以及成員變量契吉。

  • 如果category中的方法和類中原有方法同名跳仿,運(yùn)行時會優(yōu)先調(diào)用category中的方法。也就是捐晶,category中的方法會覆蓋掉類中原有的方法菲语。所以開發(fā)中盡量保證不要讓分類中的方法和原有類中的方法名相同。避免出現(xiàn)這種情況的解決方案是給分類的方法名統(tǒng)一添加前綴惑灵。比如category_山上。

  • 如果多個category中存在同名的方法,運(yùn)行時到底調(diào)用哪個方法由編譯器決定英支,最后一個參與編譯的方法會被調(diào)用佩憾。

3、調(diào)用優(yōu)先級

分類(category) > 本類 > 父類干花。即妄帘,優(yōu)先調(diào)用cateory中的方法,然后調(diào)用本類方法池凄,最后調(diào)用父類方法抡驼。

Category的底層結(jié)構(gòu)

  • 定義在objc-runtime-new.h 中

      struct category_t{
          const char*name;
          classref_t cls;
          struct method_list_t*instanceMethods;
          struct method_list_t *classMethods;
          struct proptocol_list_t *protoclos;
          sturct property_list *instanceProperties;
          struct property_list_t *_classProperties;
    
        method_list_t *methodsForMeta(bool isMeta){
        if(isMeta) return classMethods;
        else return instanceMethods;
        
        property_list_t *proertiesForMeta(bool isMeta,stuct header_info*hi);
        }
    
      }
    

Category加載過程

  1. 通過Runtime加載某個類所有的Category數(shù)據(jù)
  2. 把所有的Category 的方法、屬性肿仑、協(xié)議數(shù)據(jù)致盟,合并到一個大數(shù)組中。后面圖片中?后面參與編譯的Category數(shù)據(jù)柏副,回在數(shù)組的前面勾邦。
  3. 將合并的分類數(shù)據(jù)(方法、屬性割择、協(xié)議)眷篇,插入到類原來的數(shù)據(jù)前面。


    E47E26A9-B4D9-4753-807E-62E8324FB25F.png
load 方法的調(diào)用
  • +load 方法會在runtime加載類荔泳、分類時調(diào)用蕉饼。

  • 每個分類、類的load方法玛歌,在程序運(yùn)行中只調(diào)用一次

  • 調(diào)用順序
    1 先調(diào)用類的load方法
    2 按照編譯先后順序調(diào)用(先編譯昧港,先調(diào)用)
    3 調(diào)用子類的load 方法之前回先調(diào)用父類的+load 方法。

    分類
    1 在調(diào)用分類的load方法
    2 按照編譯先后順序調(diào)用先(先編譯支子,先調(diào)用)创肥。

+initizlize方法

+initialize 方法會在類的第一次接收到消息時調(diào)用。

  • 調(diào)用順序
    先調(diào)用父類的initzlize ,在調(diào)用子類的initialize
    先初始化父類叹侄,在初始化子類巩搏,每個類只會初始化一次。

  • initialize 和load 的最大區(qū)別
    initialize時通過objc_msgSend進(jìn)行調(diào)用的
    如果子類沒有實現(xiàn)initialize 會調(diào)用父類的initialize(所以父類的的initialize可能會被剁細(xì)調(diào)用)
    如果分類實現(xiàn)了initizlize 就會覆蓋類本省的initialize調(diào)用

如何給分類“添加成員變量”
  • 默認(rèn)情況下趾代,因為分類底層結(jié)構(gòu)的限制贯底,不能添加成員變量到分類中。但是可以通過關(guān)聯(lián)對象來說實現(xiàn)撒强。

  • 關(guān)聯(lián)對象的API

      添加關(guān)聯(lián)對象
      void objc_setAssociatedObject(id object,const voie *key,id value,objc_associationPolicy policy)
      獲取關(guān)聯(lián)對象
      id objc_getAssociatedObject(id object,const void *key)
      移除所有的關(guān)聯(lián)對象
      void objc——removeAssociatedObjects(Id object)
    
  • key的常見用法

        static void *MyKey = &Mykey;
        objc_setAssociatedObject(obj,MYkey,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        objc_getASSOciatedObjct(obj,Mykey);
    
      static chat Mykey;
       objc_setAssociatedObject(obj,&Mykey,value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj,&Mykey);
    
      使用屬性名作為key
     objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
      objc_getAssociatedObject(obj, @"property");
    
      使用get方法的@selecor作為key
      objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
      objc_getAssociatedObject(obj, @selector(getter))
    

關(guān)聯(lián)對象的原理

實現(xiàn)管來呢對象技術(shù)的核心對象有

  • AssociationsManager
  • AssociationsHashMap
  • ObjectAssociationMap
  • ObjectAssociation
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末禽捆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子飘哨,更是在濱河造成了極大的恐慌胚想,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芽隆,死亡現(xiàn)場離奇詭異顿仇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)摆马,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸿吆,“玉大人囤采,你說我怎么就攤上這事〕痛荆” “怎么了蕉毯?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長思犁。 經(jīng)常有香客問我代虾,道長,這世上最難降的妖魔是什么激蹲? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任棉磨,我火速辦了婚禮,結(jié)果婚禮上学辱,老公的妹妹穿的比我還像新娘乘瓤。我一直安慰自己,他們只是感情好策泣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布衙傀。 她就那樣靜靜地躺著,像睡著了一般萨咕。 火紅的嫁衣襯著肌膚如雪统抬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機(jī)與錄音聪建,去河邊找鬼钙畔。 笑死,一個胖子當(dāng)著我的面吹牛妆偏,可吹牛的內(nèi)容都是我干的刃鳄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钱骂,長吁一口氣:“原來是場噩夢啊……” “哼叔锐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起见秽,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤愉烙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后解取,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體步责,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年禀苦,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔓肯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡振乏,死狀恐怖蔗包,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情慧邮,我是刑警寧澤调限,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站误澳,受9級特大地震影響耻矮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜忆谓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一裆装、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧倡缠,春花似錦米母、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至桅滋,卻和暖如春慧耍,著一層夾襖步出監(jiān)牢的瞬間身辨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工芍碧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留煌珊,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓泌豆,卻偏偏與公主長得像定庵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踪危,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容