iOS 探討category和extension

一、分類(Category)

想必大家都知道我們可以在分類中為某個類擴(kuò)展方法,并且通過分類添加的方法的優(yōu)先級還高于原始類中的方法,即如果分類中和原始類中有相同的方法,那我們調(diào)用時是優(yōu)先調(diào)用通過分類添加的方法。
既然通過分類能給類添加方法,那能不能給類添加屬性呢?屬性中綁定了一個成員變量,那分類又能不能給類添加成員變量呢?今天元宵節(jié),閑著沒事,就此調(diào)研了一番。

論點

(1) 分類可以給類添加屬性
(2) 分類不可以給一個類擴(kuò)展成員變量的`

先嘮嘮嗑

強調(diào)一下,分類不是類,它只是一個類似匿名擴(kuò)展(下面會討論擴(kuò)展)的模塊,用于擴(kuò)展給類添加方法,便于協(xié)作、分模塊的開發(fā),你看看蘋果提供的很多API都是這樣,蘋果會寫很多分類來給某個類添加不同的功能,一來結(jié)構(gòu)清晰,二來也便于協(xié)同開發(fā),可以每個人負(fù)責(zé)一個分類。

我們都知道,OC的世界里,任何集成自NSObject的對象都有isa指針,他本質(zhì)是一個結(jié)構(gòu)體指針,但是對于Category來說,他是沒有isa指針的,好了,下面進(jìn)行論證一番。

論據(jù)

先說說屬性,屬性是對成員變量的一個封裝,當(dāng)我們聲明一個屬性的時候,Xcode會給我們默認(rèn)創(chuàng)建一個 _屬性名 命名的成員變量,也會給我們自動創(chuàng)建getter和setter方法。當(dāng)然我們也可以用@synthesize指定其關(guān)聯(lián)的變量

【例如】給屬性name指定其關(guān)聯(lián)的變量@synthesize name = xxx;執(zhí)行self.name的時候,其實是操作的是實例變量xxx,而不是_name了。

窩草,扯遠(yuǎn)了,回歸正傳。。

所以我們要添加一個屬性得有三樣?xùn)|西,setter、getter以及關(guān)聯(lián)的實例變量。

在分類中Xcode不會為我們自動創(chuàng)建setter、getter方法,但是我們可以手動實現(xiàn),但是如何把一個變量關(guān)聯(lián)到屬性上呢,直接聲明一個全局變量不行嗎,事實證明不太行,對于getter方法還好說,直接返回一個變量就行,可是setter方法卻不行,因為你要找到該屬性關(guān)聯(lián)的變量你才能給人家賦值啊,怎么辦?怎么辦??經(jīng)過調(diào)研發(fā)現(xiàn)這只能用runtime的對象關(guān)聯(lián)來實現(xiàn)了

.m文件中
// 定義關(guān)聯(lián)的key
static const char *key = "name";

@implementation NSObject (Property)

-  (NSString *)name {
  // 根據(jù)關(guān)聯(lián)的key,獲取關(guān)聯(lián)的值。
  return objc_getAssociatedObject(self, key);
}

-  (void)setName:(NSString *)name {
  // 參數(shù)一:目標(biāo)對象
  // 參數(shù)二:關(guān)聯(lián)的key,可以通過這個key獲取
  // 參數(shù)三:關(guān)聯(lián)的value
  // 參數(shù)四:關(guān)聯(lián)的策略
  objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

看到這里你也許就會說,這不是把變量給添加上去了嗎?我表示默默一笑,如果你在原始類中打印IVarList你就會發(fā)現(xiàn)并沒有這個變量,只能打印出添加的屬性。
其實對象關(guān)聯(lián)只是把屬性關(guān)聯(lián)上去了,并沒有把變量添加進(jìn)去,說了這么多這回你該信了吧。

原因就是分類不是類,他沒有isa指針,下面是isa指針的代碼,可以看出他本質(zhì)上是一個objc_class結(jié)構(gòu)體,通過isa指針才能找指向裝有變量的ivars容器,也就是說你都不知道裝有變量的容器ivars,你怎么去給它生猴子啊,但是奇怪了,ISA指針里沒有指向?qū)傩詳?shù)組的指針,沒有是對的,要不然這一段的解釋就廢了,可是講真,屬性指針在哪?。???有知道的小伙伴請告訴我一下 >_< !!!

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

結(jié)論

分類中可以給一個對象添加屬性,但是不能添加實例變量,只能通過運行時關(guān)聯(lián)上去。
注意:如果不信,你可以在原始類中打印一遍吧,會發(fā)現(xiàn)只能打印出添加的屬性,打印不出變量。

二、擴(kuò)展(Extension)

在分類中,我們可以添加屬性,聲明方法,但是這些都是私有的,因為你無法把擴(kuò)展給導(dǎo)出去啊,這就是和category的一個區(qū)別。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 把網(wǎng)上的一些結(jié)合自己面試時遇到的面試題總結(jié)了一下,以后有新的還會再加進(jìn)來。 1. OC 的理解與特性 OC 作為一...
    AlaricMurray閱讀 2,667評論 0 20
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,058評論 0 9
  • Getting started(入口)Welcome to Training for Android develo...
    AiPuff閱讀 239評論 0 0
  • 或許是夏天快要來了的原因,天氣變得讓人感到異常悶熱,寫作業(yè)寫得特別煩躁,根本寫不進(jìn)去,效率很低。為了緩解下心...
    7e閱讀 470評論 0 3
  • 親愛的媽媽: 昨天,我得知你送咪貝上編程課的時候和周老師聊了會天。你告訴周老師,驚喜地看到自己的女兒越來越出色,連...
    葛瑛閱讀 237評論 2 6

友情鏈接更多精彩內(nèi)容