深入理解OC面向?qū)ο?/h1>

目錄

  • 1.面向?qū)ο?/p>

    • 1.三要素
    • 2.屬性
  • 2.深拷貝與淺拷貝

    • 1.Foundation框架中的對(duì)象
    • 2.自定義對(duì)象
  • 3.對(duì)象等同性

    • 1.NSString對(duì)象判斷相等
    • 2.自定義對(duì)象判斷相等
  • 4.KVC / KVO

    • 1.KVC的過(guò)程
    • 2.KVO的原理
  • 5.Category

    • 1.Category的使用場(chǎng)合
    • 2.Category的實(shí)現(xiàn)原理
    • 3.關(guān)聯(lián)對(duì)象
  • 6.+load和+initialize

一、面向?qū)ο?/h2>

1.面向?qū)ο笕齻€(gè)要素

1.1 封裝

概念:隱藏對(duì)象的數(shù)據(jù)缭乘,不允許外界直接訪(fǎng)問(wèn)凉唐,而是需要通過(guò)相應(yīng)的方法來(lái)訪(fǎng)問(wèn)和修改數(shù)據(jù)拿愧。
實(shí)現(xiàn):OC使用屬性(property)來(lái)封裝對(duì)象中的數(shù)據(jù)空猜。

1.2 繼承

概念:通過(guò)繼承子類(lèi)可以得到父類(lèi)屬性和方法则北,在父類(lèi)的基礎(chǔ)上建立新的類(lèi)邢隧。
實(shí)現(xiàn):OC的消息機(jī)制在自己的類(lèi)信息中找不到對(duì)應(yīng)方法時(shí)粱坤,會(huì)通過(guò)superclass指針去父類(lèi)的類(lèi)信息中查找隶糕。

1.3 多態(tài)

概念:子類(lèi)重寫(xiě)父類(lèi)方法,父類(lèi)指針指向子類(lèi)站玄,父類(lèi)指針調(diào)用方法時(shí)會(huì)調(diào)用子類(lèi)重寫(xiě)的方法枚驻。
實(shí)現(xiàn):

Q:iOS如何實(shí)現(xiàn)多繼承?

最符合的方式是消息轉(zhuǎn)發(fā)株旷;

其他的方式也有

  • 組合:將類(lèi)A和類(lèi)B的實(shí)例對(duì)象作為類(lèi)C的屬性再登;
  • delegate和protocol:將C類(lèi)需要繼承的方法以及屬性在ClassA和ClassB中各自聲明一份協(xié)議,C類(lèi)遵守這兩份協(xié)議,同時(shí)在C類(lèi)中實(shí)現(xiàn)協(xié)議中的方法以及屬性

Q:OC有重載嗎霎冯?

重載說(shuō)的是函數(shù)名相同铃拇,但是參數(shù)不同,OC沒(méi)有沈撞。swift支持重載慷荔。

2.屬性(@property)

在類(lèi)定義中聲明的屬性,編譯器會(huì)自動(dòng)生成一個(gè)與該屬性同名且下劃線(xiàn)開(kāi)頭的成員變量缠俺,同時(shí)自動(dòng)生成該實(shí)例變量的存取方法显晶。

可以通過(guò)修改屬性的修飾詞來(lái)控制存取方法的生產(chǎn),修飾詞有四種:

  • 原子性:atomic壹士、noatomic
  • 內(nèi)存管理語(yǔ)義:copy磷雇、strong、assign躏救、weak
  • 讀寫(xiě)權(quán)限:readonly唯笙、readwrite
  • 方法名:getter=、setter=

二盒使、深拷貝與淺拷貝

深拷貝就是內(nèi)容拷貝崩掘,淺拷貝就是指針拷貝。本質(zhì)區(qū)別在于:

  • 是否開(kāi)啟新的內(nèi)存地址
  • 是否影響內(nèi)存地址的引用計(jì)數(shù)

1.Foundation框架中的對(duì)象

對(duì)Foundation框架中的非容器對(duì)象(NSString少办、NSNumber)和容器對(duì)象(NSArray苞慢、NSDictionary)使用copymutableCopy的情況如下:

需要注意的是,容器對(duì)象的深拷貝其實(shí)是單層深拷貝英妓。
單層深拷貝:雖然為數(shù)組對(duì)象開(kāi)辟了新空間挽放,不過(guò)存放在數(shù)組的值還是原數(shù)組元素值。

實(shí)現(xiàn)容器對(duì)象的完全深拷貝可以使用專(zhuān)門(mén)的方法
- (instancetype)initWithArray:(NSArray *)array copyItems:(BOOL)flag;

Q:為什么NSString屬性用copy修飾蔓纠?
因?yàn)榭赡軙?huì)把NSMutableString對(duì)象賦值給NSString屬性辑畦;
如果使用strong的話(huà),對(duì)象外面的可變對(duì)象發(fā)生改變時(shí)腿倚,對(duì)象內(nèi)部的NSString屬性也會(huì)跟著變化航闺。
而使用copy可以避免這個(gè)情況,賦值時(shí)會(huì)拷貝一份不可變副本賦值給NSString屬性猴誊。

2.自定義對(duì)象

遵循 NSCopying 協(xié)議,實(shí)現(xiàn)- (id)copyWithZone:(NSZone *)zone方法侮措。

三懈叹、對(duì)象等同性

1.NSString對(duì)象判斷相等

NSString中判斷相等有三個(gè)方法:isEqualisEqualToString分扎、==澄成,它們的區(qū)別在于:

  • ==:直接比較兩個(gè)對(duì)象的地址
  • isEqual:NSString重寫(xiě)了該方法,首先判斷兩個(gè)對(duì)象的類(lèi),然后判斷兩個(gè)對(duì)象的內(nèi)容墨状。
  • isEqualToString:判斷兩個(gè)字符串內(nèi)容是否相同卫漫。
    因?yàn)樯倭藱z測(cè)參數(shù)類(lèi)型,所以比isEqual快肾砂。
    事實(shí)上isEqual在檢測(cè)完參數(shù)類(lèi)型后列赎,就調(diào)用了該函數(shù)。

2.自定義對(duì)象判斷相等

重寫(xiě)isEqual方法:

  • 首先镐确,直接判斷兩個(gè)指針是否相等包吝;
  • 接下來(lái),判斷是否都屬于一個(gè)類(lèi)源葫。
  • 最后诗越,檢測(cè)每個(gè)屬性值是否相等。

另外:重寫(xiě)了isEqual方法息堂,那么也必須重寫(xiě)hash方法嚷狞。因?yàn)槿绻麅蓚€(gè)對(duì)象相等,那么它們也必須有相同的哈希值荣堰。不過(guò)反之則不成立床未。

@interface HJPerson : NSObject
@property (nonatomic, copy) NSString* firstName;
@property (nonatomic, copy) NSString* lastName;
@property (nonatomic, assign) NSUInteger age;
@end

@implementation HJPerson
- (BOOL)isEqual:(id)other{
    if (self == other) return YES;
    if ([self class] != [other class]) return NO;
    
    HJPerson* otherPerson = (HJPerson*)other;
    if (![self.firstName isEqualToString:otherPerson.firstName]) return NO;
    if (![self.lastName isEqualToString:otherPerson.lastName]) return NO;
    if (self.age != otherPerson.age) return NO;
    
    return YES;
}
- (NSUInteger)hash{
    NSUInteger firstNameHash = [self.firstName hash];
    NSUInteger lastNameHash = [self.lastName hash];
    NSUInteger ageHash = self.age;
    return firstNameHash ^ lastNameHash ^ ageHash;
}
@end

四 、KVC / KVO

1.KVC的過(guò)程

(1)按照命名規(guī)范持隧,先查找相關(guān)的方法即硼,如果沒(méi)有找到;
(2)按照命名規(guī)范屡拨,找相關(guān)的成員變量只酥,如果沒(méi)有找到;
(3)調(diào)用setValue:forUndefinedKey呀狼;
(4)如果都沒(méi)有找到相關(guān)的方法實(shí)現(xiàn)就拋出異常裂允。


2.KVO實(shí)現(xiàn)機(jī)制

一個(gè)類(lèi)添加觀察者后,runtime創(chuàng)建了一個(gè)該類(lèi)的派生類(lèi)哥艇!實(shí)例對(duì)象的isa指向這個(gè)派生類(lèi)绝编。如果該類(lèi)有setter方法,在派生類(lèi)中會(huì)重寫(xiě)了setter方法貌踏。

重寫(xiě)的setter函數(shù)的實(shí)現(xiàn)大概是這樣:

然后在didChangeValueForKey中調(diào)用觀察者的observeValueForKeyPath十饥。

Q:如何手動(dòng)觸發(fā)KVO?

(1)關(guān)掉屬性的自動(dòng)觸發(fā)
(2)在setter方法中祖乳,手動(dòng)調(diào)用willChangeValueForKey和didChangeValueForKey

五逗堵、Category

1.Category的使用場(chǎng)合

  • 將類(lèi)拆解為幾個(gè)模塊
  • 為現(xiàn)有的類(lèi)添加一些方法

2.Category的實(shí)現(xiàn)原理

Category的底層結(jié)構(gòu)其實(shí)是struct _category_t 結(jié)構(gòu)體,里面存儲(chǔ)著Category的方法眷昆、屬性蜒秤、協(xié)議等信息汁咏。在運(yùn)行時(shí)、runtime初始化的時(shí)候作媚,會(huì)將category的數(shù)據(jù)攘滩,合并到類(lèi)信息中。

Q:Category和Extension的區(qū)別是什么纸泡?

  • Extension的數(shù)據(jù)在編譯時(shí)就合并到類(lèi)信息中了漂问。
  • Category的數(shù)據(jù)在運(yùn)行時(shí)才會(huì)合并到類(lèi)信息中。

Q:類(lèi)和分類(lèi)中的方法名相同弟灼,會(huì)調(diào)用哪個(gè)方法级解?

  • 對(duì)于類(lèi)中和分類(lèi)中的同名方法,會(huì)優(yōu)先調(diào)用分類(lèi)的方法田绑,因?yàn)榉诸?lèi)的方法會(huì)放在原來(lái)的方法前面勤哗。

  • 對(duì)于多個(gè)分類(lèi)中的同名方法,則需要看編譯順序掩驱。最后面編譯的分類(lèi)芒划,其方法會(huì)放在前面。

注:核心源代碼attachCategories()欧穴、attachLists()民逼。

3.關(guān)聯(lián)對(duì)象

Category不能添加成員變量,關(guān)聯(lián)對(duì)象用于給Category“添加成員變量”涮帘。

關(guān)聯(lián)對(duì)象的API:

  • 添加關(guān)聯(lián)對(duì)象:void objc_setAssociatedObject(id object, const void * key,
    id value, objc_AssociationPolicy policy)

  • 獲得關(guān)聯(lián)對(duì)象:id objc_getAssociatedObject(id object, const void * key)

  • 移除所有的關(guān)聯(lián)對(duì)象:void objc_removeAssociatedObjects(id object)

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

關(guān)聯(lián)對(duì)象是使用哈希表實(shí)現(xiàn)的拼苍,將被關(guān)聯(lián)的對(duì)象作為key,映射到一個(gè)子哈希表上调缨。然后再通過(guò)變量名找到值疮鲫。而不是將變量放在被關(guān)聯(lián)的對(duì)象中。

Q:Category能否添加成員變量弦叶?為什么俊犯?

不能。因?yàn)镃ategory的底層數(shù)據(jù)結(jié)構(gòu)伤哺,它的結(jié)構(gòu)體中沒(méi)有成員變量只有屬性燕侠。

六、+load和+initialize

1.+load方法

+load方法會(huì)在這個(gè)類(lèi)加載到內(nèi)存中被調(diào)用立莉【钔或者說(shuō)在runtime加載類(lèi)、分類(lèi)的時(shí)候調(diào)用蜓耻。

注意:

  • 就算在mian.h中沒(méi)有導(dǎo)入這個(gè)類(lèi)或者沒(méi)有使用這個(gè)類(lèi)茫舶,+load方法也會(huì)調(diào)用。
  • +load方法在被runtime自動(dòng)調(diào)用時(shí)媒熊,是直接取出+load方法奇适,而不是經(jīng)過(guò)objc_msgSend,所以不遵循繼承規(guī)則芦鳍,類(lèi)和分類(lèi)的load方法都會(huì)被調(diào)用嚷往。
MJPerson +load
MJStudent +load
MJPerson (Test1) +load
MJPerson (Test2) +load
MJStudent (Test1) +load
MJStudent (Test2) +load

2.+initialize方法

+initialize方法是在類(lèi)第一次發(fā)送消息的時(shí)候調(diào)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末柠衅,一起剝皮案震驚了整個(gè)濱河市皮仁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菲宴,老刑警劉巖贷祈,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異势誊,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)谣蠢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)粟耻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人眉踱,你說(shuō)我怎么就攤上這事挤忙。” “怎么了谈喳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵册烈,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我婿禽,道長(zhǎng)赏僧,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任谈宛,我火速辦了婚禮次哈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吆录。我一直安慰自己窑滞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布恢筝。 她就那樣靜靜地躺著哀卫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撬槽。 梳的紋絲不亂的頭發(fā)上此改,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音侄柔,去河邊找鬼共啃。 笑死占调,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的移剪。 我是一名探鬼主播究珊,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纵苛!你這毒婦竟也來(lái)了剿涮?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤攻人,失蹤者是張志新(化名)和其女友劉穎取试,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體怀吻,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞬浓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烙博。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瑟蜈。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖渣窜,靈堂內(nèi)的尸體忽然破棺而出铺根,到底是詐尸還是另有隱情,我是刑警寧澤乔宿,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布位迂,位于F島的核電站,受9級(jí)特大地震影響详瑞,放射性物質(zhì)發(fā)生泄漏掂林。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一坝橡、第九天 我趴在偏房一處隱蔽的房頂上張望泻帮。 院中可真熱鬧,春花似錦计寇、人聲如沸锣杂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)元莫。三九已至,卻和暖如春蝶押,著一層夾襖步出監(jiān)牢的瞬間踱蠢,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工棋电, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茎截,地道東北人苇侵。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像企锌,于是被迫代替她去往敵國(guó)和親衅檀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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